怎麼樣才能將貨櫃快速交給不同鯨魚呢? 來做點模板吧~
圖片來源:Docker (@Docker) / Twitter
上一篇完成了 dockerfile 並用 docker network 測試連線,最後將 image 推上 harbor
今天來看看怎麼部署到 kubernetes ~
首先要先確認部署的 node 能從 Harbor 取得 image
因為 Harbor 有做權限控管,因此需要建立一個帳號,登入後才能取得所屬的 image
可以為項目建立機器人帳號,方便部署、測試使用

可以自行挑選機器人帳號可用權限
最後會顯示帳號及 token (按下複製後就會自動關掉彈跳窗,關掉後就沒辦法再看到了)
確認一下可以登入~
$ docker login https://harbor.example.domain.com 
Username: robot$test-web+test-web-robot
Password: 
Login Succeeded
接著來寫 kubernetes resource
先建立一個 namespace test-web
kubectl create ns test-web
在要部署的 cluter 上建立 secret,做為登入 harbor 使用的帳號密碼
kubectl create secret docker-registry -n test-web test-web-robot \
    --docker-server=https://harbor.example.com \
    --docker-username='robot$test-web+test-web-robot' \
    --docker-password=<your_password>
機器人帳號有特殊字元
$記得使用'
後端需要一個 volume 儲存資料,這裡使用 PVC 和前幾篇建立的 nfs StorageClass 請求 PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: backend-data
  namespace: test-web
  labels:
    app: backend-data
spec:
  storageClassName: nfs-client
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
建立一個基本的 deployment
imagePullSecrets secret 才能從 Harbor 上取得 imageapiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: test-web
  labels:
    app: backend
spec:
  selector:
    matchLabels:
      app: backend
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: backend
    spec:
      imagePullSecrets:
        - name: test-web-robot
      initContainers:
        - name: init
          image: alpine:3.16.2
          command: ["/bin/sh", "-c"]
          args:
            - echo '["aaa","bbb","ccc"]' > /app/data/todos.json
          volumeMounts:
            - name: data
              mountPath: /app/data
      containers:
        - name: backend
          image: harbor.example.domain.com/test-web/test-backend:dev
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
            limits:
              cpu: 100m
              memory: 100Mi
          livenessProbe:
            tcpSocket:
              port: 80
            initialDelaySeconds: 5
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            timeoutSeconds: 2
            successThreshold: 1
            failureThreshold: 3
            periodSeconds: 10
          env:
            - name: HOST_PORT
              value: "80"
          ports:
            - containerPort: 80
              name: backend
          volumeMounts:
            - name: data
              mountPath: /app/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: backend-data
      restartPolicy: Always
最後為 backend 建立一個 service 讓 frontend 能夠接到
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: test-web
spec:
  selector:
    app: backend
  type: ClusterIP
  sessionAffinity: None
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
  - name: backend
    protocol: TCP
    port: 80
    targetPort: 80
建立一個基本的 deployment,記得指定使用 Harbor 上的 frontend image
imagePullSecrets secret 才能從 Harbor 上取得 imageapiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: test-web
  labels:
    app: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: frontend
    spec:
      imagePullSecrets:
        - name: test-web-robot
      containers:
        - name: frontend
          image: harbor.example.domain.com/test-web/test-frontend:dev
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
            limits:
              cpu: 100m
              memory: 100Mi
          livenessProbe:
            tcpSocket:
              port: 80
            initialDelaySeconds: 5
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            timeoutSeconds: 2
            successThreshold: 1
            failureThreshold: 3
            periodSeconds: 10
          env:
            - name: BACKEND_URL
              value: backend
          ports:
            - containerPort: 80
              name: frontend
      restartPolicy: Always
為 frontend 建立 Service
apiVersion: v1
kind: Service
metadata:
  name: frontend
  namespace: test-web
spec:
  selector:
    app: frontend
  type: ClusterIP
  sessionAffinity: None
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
  - name: frontend
    protocol: TCP
    port: 80
    targetPort: 80
建立 Ingress,使用前幾篇建立的 Traefik 協助 expose 網站
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-web
  namespace: test-web
  labels:
    environment: production
    method: traefik
spec:
  rules:
  - host: test-web.example.domain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

明天繼續建立 helm chart~