Day 26 – CDK builds Amazon Elastic Kubernetes Service (EKS)-Service

2020 12th 鐵人賽

昨天介紹完了 Cluster 今天來介紹如何使用 CDK 建立 EKS Service 往常我們如果使用 kubectl 要新增服務或是控制都會需要用到 yaml 檔案,但今天我們使用 CDK 部署 EKS 不用使用到 yaml,那我們要怎麼控制 Kubernetes(K8S)呢? 我們用 typescript 寫 CDK 當然就是直接寫 JSON 拉!是不是很神奇呢?快點跟著我看下去吧!

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201012/201177017ZDM9OEOb9.png?w=640&ssl=1

部署目標

在部署前我們先整理一下這次目標需要什麼

  1. 部署一個服務名稱:hello-kubernetes
  2. replicas 設定為:3
  3. Docker Image 使用:paulbouwer/hello-kubernetes:1.5
  4. Container 內部 port 為:8080
  5. 設定一個 LoadBalancer 外部 port 為 80 對接內部的 hello-kubernetes 服務

部署 EKS Service

定義 Deployment

整理好後我們先設定 Deployment 以部署 Kubernetes(K8S)的 YAML 來說,我們要處理 Container 名稱、數量、內部 Port

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels: hello-kubernetes
  template:
    metadata:
      labels: hello-kubernetes
    spec:
      containers:
        - name: hello-kubernetes
          image: 'paulbouwer/hello-kubernetes:1.5'
          ports:
            - containerPort: 8080

但我們說過我們這次的部署不需要 YAML 所以我們直接使用 TypeScript 來寫

const appLabel = { app: "hello-kubernetes" };

const deployment = {
  apiVersion: "apps/v1",
  kind: "Deployment",
  metadata: { name: "hello-kubernetes" },
  spec: {
    replicas: 3,
    selector: { matchLabels: appLabel },
    template: {
      metadata: { labels: appLabel },
      spec: {
        containers: [
          {
            name: "hello-kubernetes",
            image: "paulbouwer/hello-kubernetes:1.5",
            ports: [{ containerPort: 8080 }],
          },
        ],
      },
    },
  },
};

Deployment 部署方法可以參考 kubernetes Documentation

定義 Service

而在部署 Kubernetes(K8S)的 Service YAML,需要處理 LoadBalancer 外部 port 與內部 Service 的對應

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8080
  selector: hello-kubernetes

想好後轉換成 TypeScript 的程式

const service = {
  apiVersion: "v1",
  kind: "Service",
  metadata: { name: "hello-kubernetes" },
  spec: {
    type: "LoadBalancer",
    ports: [{ port: 80, targetPort: 8080 }],
    selector: appLabel,
  },
};

Service 部署方法可以參考 kubernetes Documentation

設定 Manifest

往常使用 Kubernetes(K8S)我們需要使用 kubectl apply -f hello-kubernetes.yaml 而在 CDK 我們可以直接使用 addManifest 塞入 cluster 就做完了!

cluster.addManifest("mypod", service, deployment);

顯示 Load Balancer

在使用 Kubernetes(K8S 需要使用 kubectl get rc,services 取得我們 Service 的位置,那使用 CDK 可以直接讓它在部署的時候用 Output 直接吐出來!從此可以不用再使用 kubectl 拉!ヽ(✿゚▽゚)ノ

new cdk.CfnOutput(this, "LoadBalancer", {
  value: cluster.getServiceLoadBalancerAddress("hello-kubernetes"),
});

測試

說了這麼多我們來部署測試看看吧!雖然上面說我們不需要用到 kubectl 不過我們還是需要用它來進行測試確定系統有沒有如所想的部署執行一下 cdk deploy 等它 15 ~ 30 分鐘吧! ( • ̀ω•́ )

執行完後的 Output:

Outputs:
CdkEksStack.LoadBalancer = aba304eea204b4239abb905439ac8ec7-1947016485.us-west-2.elb.amazonaws.com
CdkEksStack.eksConfigCommandDB09280A = aws eks update-kubeconfig --name eksB49B8EA3-7fcd6a64ed934f00ae43ec1cb67a87fa --region us-west-2 --role-arn arn:aws:iam::869989823608:role/CdkEksStack-mastersRole634808EE-1I504Q4EPLS70
CdkEksStack.eksGetTokenCommand8952195F = aws eks get-token --cluster-name eksB49B8EA3-7fcd6a64ed934f00ae43ec1cb67a87fa --region us-west-2 --role-arn arn:aws:iam::869989823608:role/CdkEksStack-mastersRole634808EE-1I504Q4EPLS70

AWS Console 的 Load balancer

可以看到在 AWS Load balancer 建立了一個 classic 的服務而他的 DNS 如上面的 CDK Output https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701vyK5sehqiW.png?w=640&ssl=1

而在 Instances 可以看到我們的 Cluster 機器確實註冊在這個 Load balancer 後面 https://i0.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701oJz1LTTEKH.png?w=640&ssl=1

Tags 可以看到有些設定被定義 https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701MCGv87KYvN.png?w=640&ssl=1

查看 Kubernetes replicas 數量

可以使用 kubectl get pods 看到我們的 replicas 確實有設定為 3

$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
hello-kubernetes-5655b546f8-cm66l   1/1     Running   0          49m
hello-kubernetes-5655b546f8-l8xkj   1/1     Running   0          49m
hello-kubernetes-5655b546f8-msjh6   1/1     Running   0          49m
mypod                               1/1     Running   0          97m

查看 Kubernetes Services 的部署狀態

使用 kubectl get rc,services 查看我們的 Load Balancer 確實也與 AWS Console 顯示的一樣

$ kubectl get rc,services
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP                                                               PORT(S)        AGE
service/hello-kubernetes   LoadBalancer   172.20.200.52   aba304eea204b4239abb905439ac8ec7-1947016485.us-west-2.elb.amazonaws.com   80:30139/TCP   35m
service/kubernetes         ClusterIP      172.20.0.1      <none>                                                                    443/TCP        3h35m

瀏覽一下 Kubernetes 部署的網頁

瀏覽一下剛剛部署的 LoadBalancer 可以看到我們的 pod id 每次都不一樣,如剛剛部署的 replicas 數量會有三個輪流吃到我們的 request

https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701I7raDeZn4h.png?w=640&ssl=1

https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701ezeaxLkeAi.png?w=640&ssl=1

https://i0.wp.com/ithelp.ithome.com.tw/upload/images/20201009/20117701L7V9fMO1DA.png?w=640&ssl=1

查看 pod log

雖然我們這邊主要不是介紹 Kubernetes 不過順便提一下如果想要看到 pod 的 log 可以使用 kubectl logs 帶上 id 查看 Log

$ kubectl logs hello-kubernetes-5655b546f8-cm66l
npm info it worked if it ends with ok
npm info using npm@5.0.3
npm info using node@v8.1.0
npm info lifecycle hello-kubernetes@1.5.0~prestart: hello-kubernetes@1.5.0
npm info lifecycle hello-kubernetes@1.5.0~start: hello-kubernetes@1.5.0

> hello-kubernetes@1.5.0 start /usr/src/app
> node server.js

Listening on: http://hello-kubernetes-5655b546f8-cm66l:8080
::ffff:10.0.255.11 - - [09/Oct/2020:11:17:29 +0000] "GET / HTTP/1.1" 200 667 "-" "curl/7.64.1"
::ffff:10.0.255.11 - - [09/Oct/2020:11:17:40 +0000] "GET /favicon.ico HTTP/1.1" 404 150 "http://aba304eea204b4239abb905439ac8ec7-1947016485.us-west-2.elb.amazonaws.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36"

今天介紹 CDK 可以神奇的處理很多原本要用 kubectl 才可以處理的事情是不是超神奇的啊!!!