Kubernetes operator for managing TeamCity
10K+
TeamCity Operator is a Kubernetes operator that deploys and manages TeamCity servers using a Custom Resource Definition (CRD).
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.3/cert-manager.yaml
Install release 0.0.20 of the chart from GitHub Releases:
helm upgrade --install teamcity-operator \
-n teamcity-operator --create-namespace \
https://github.com/JetBrains/teamcity-operator/releases/download/0.0.20/teamcity-operator-0.0.20.tgz
From the repository root of this project:
helm upgrade --install teamcity-operator \
-n teamcity-operator --create-namespace \
./charts/teamcity-operator
Verify installation:
kubectl get pods -n teamcity-operator
kubectl get crd teamcities.jetbrains.com
After installing the operator, apply a TeamCity custom resource. Below are common configurations. You can find additional samples under config/samples/v1beta1.
Note: When setting CPU and memory requests/limits for nodes, consult the official TeamCity Server Requirements to estimate appropriate resources: https://www.jetbrains.com/help/teamcity/system-requirements.html#TeamCity+Server+Requirements.
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
mainNode:
name: main-node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: v1
data:
connectionProperties.password: DB_PASSWORD
connectionProperties.user: DB_USER
connectionUrl: DB_CONNECTION_STRING # format jdbc:mysql://DB_HOST:DB_PORT/SCHEMA_NAME
kind: Secret
metadata:
name: database-properties
---
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-with-database
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
databaseSecret:
secret: database-properties
mainNode:
name: main-node
spec:
env:
AWS_DEFAULT_REGION: "eu-west-1"
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-with-startup-properties
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
startupPropertiesConfig:
teamcity.startup.maintenance: "false"
teamcity.firstStart.setupAdmin.enabled: "false"
mainNode:
name: main-node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-sample-with-ingress
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
mainNode:
name: main-node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
serviceList:
- name: main-node
spec:
selector:
app.kubernetes.io/name: teamcity-sample-with-ingress
app.kubernetes.io/component: teamcity-server
app.kubernetes.io/part-of: teamcity
ports:
- protocol: TCP
port: 8111
targetPort: 8111
clusterIP: None
ingressList:
- name: teamcity-sample-with-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/server-snippets: |
location / {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade; # WebSocket support
proxy_set_header Connection "upgrade"; # WebSocket support
}
spec:
ingressClassName: nginx
rules:
- host: teamcity.mycompany.com
http:
paths:
- backend:
service:
name: main-node
port:
number: 8111
pathType: ImplementationSpecific
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-with-service-account
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
serviceAccount:
name: teamcity-service-account
annotations:
eks.amazonaws.com/role-arn: AWS_ROLE
mainNode:
name: node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-init-containers
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
mainNode:
name: main-node
spec:
initContainers:
- name: init-myservice
image: busybox:1.28
command: [ 'sh', '-c', "echo Hello" ]
requests:
cpu: "900m"
memory: "1512Mi"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-sample-with-secondary-node-read-only
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
mainNode:
name: main-node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
secondaryNodes:
- name: secondary-node
spec:
requests:
cpu: "900m"
memory: "1512Mi"
See TeamCity multi-node responsibilities: https://www.jetbrains.com/help/teamcity/multinode-setup.html#Responsibilities
apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-sample-with-secondary-node
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
spec:
image: jetbrains/teamcity-server
startupPropertiesConfig:
teamcity.startup.maintenance: "false"
teamcity.firstStart.setupAdmin.enabled: "false"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
mainNode:
name: main-node
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
spec:
requests:
cpu: "900m"
memory: "1512Mi"
responsibilities: [ "MAIN_NODE", "CAN_PROCESS_BUILD_MESSAGES", "CAN_CHECK_FOR_CHANGES", "CAN_PROCESS_BUILD_TRIGGERS", "CAN_PROCESS_USER_DATA_MODIFICATION_REQUESTS"]
secondaryNodes:
- name: secondary-node-0
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
spec:
requests:
cpu: "900m"
memory: "1512Mi"
responsibilities: ["CAN_PROCESS_BUILD_MESSAGES", "CAN_CHECK_FOR_CHANGES", "CAN_PROCESS_BUILD_TRIGGERS", "CAN_PROCESS_USER_DATA_MODIFICATION_REQUESTS"]
- name: secondary-node-1
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
spec:
requests:
cpu: "900m"
memory: "1512Mi"
responsibilities: [ "CAN_PROCESS_BUILD_MESSAGES", "CAN_CHECK_FOR_CHANGES", "CAN_PROCESS_BUILD_TRIGGERS", "CAN_PROCESS_USER_DATA_MODIFICATION_REQUESTS" ]
Note: This is an experimental feature. Behavior and configuration may change between releases. We welcome feedback — please open an issue in this repository with your experience and suggestions.
Enables a safe upgrade flow where the operator restarts or replaces nodes in a way that keeps TeamCity available. In short: it upgrades nodes one at a time and ensures at least one node is serving the UI during the process.
Standalone Main Node setup
Multi-node setup (Main Node + Secondary TeamCity Nodes)
TeamCity resource with teamcity.jetbrains.com/update-policy: zero-downtime to turn this on.apiVersion: jetbrains.com/v1beta1
kind: TeamCity
metadata:
name: teamcity-with-zero-downtime-upgrade
namespace: default
finalizers:
- "teamcity.jetbrains.com/finalizer"
annotations:
teamcity.jetbrains.com/update-policy: zero-downtime
spec:
image: jetbrains/teamcity-server
databaseSecret:
secret: database-properties
startupPropertiesConfig:
teamcity.startup.maintenance: "false"
teamcity.firstStart.setupAdmin.enabled: "false"
dataDirVolumeClaim:
name: teamcity-data-dir
volumeMount:
name: teamcity-data-dir
mountPath: /storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
mainNode:
name: main-node
spec:
requests:
cpu: "1000m"
memory: "2500Mi"
Content type
Image
Digest
sha256:47f357c58…
Size
24.7 MB
Last updated
8 months ago
docker pull jetbrains/teamcity-operatorPulls:
232
Last week