GDG Cloud KH Meetup #4 - 給 RD 的 Kubernetes 初體驗

tags: GDG-Cloud-KH K8S
  • 今日的優惠碼,是給已沒有免費額度的人使用,若是新申請的使用者,會有 GCP 新用戶的免費額度可用。

  • Google Cloud 中文開發社群的 Telegram 群組 - https://t.me/googlecloudzhug

  • 請大家一張桌子至少坐 2 個人,這樣過程中有問題時,還有隔壁的伙伴可以討論。

前言

Agenda

  1. Containers
  2. Kubernetes
  3. Cloud (Use the Kubernetes in Cloud)

Goals

  1. Kubernetes promising trends (賣點在哪?)
  2. Adopt gradually
  3. Prepare mindset

GKE Setup

  1. Redeem Google Cloud coupon
  2. Create project in GCP

Redeem Google Cloud coupon

Please reference the workflow on paper.

cloud.google.com/redeem


Create K8s-enabled Project

  1. Go to the "Kubernetes Engine".

    https://console.cloud.google.com/projectselector2/kubernetes

  2. 建立一個新專案 (或選取之前建立好的專案)。

  3. 確定專案名稱是否是剛剛選取的名稱。

  1. 啟動 Cloud Shell (1/2)。

  2. 啟動 Cloud Shell (2/2)。

  3. Get the project ID.

    my-gke-lab1

Key in some commands

  1. gcloud config set project <PROJECT_ID>

    ​​​​chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud config set project my-gke-lab1
    ​​​​Updated property [core/project].
    
  2. gcloud config set compute/zone us-west1-a

    ​​​​chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud config set compute/zone us-west1-a
    ​​​​Updated property [compute/zone].
    
  3. gcloud container clusters create k8s201908 num-nodes 3

    ​​​​chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud container clusters create k8s201908 --num-nodes 3
    ​​​​WARNING: In June 2019, node auto-upgrade will be enabled by default for newly created clusters and node pools. To disable it, use the `--no-enable-autoupgrade` 
    ​​​​flag.
    ​​​​WARNING: Starting in 1.12, new clusters will have basic authentication disabled by default. Basic authentication can be enabled (or disabled) manually using the
    ​​​​ `--[no-]enable-basic-auth` flag.
    ​​​​WARNING: Starting in 1.12, new clusters will not have a client certificate issued. You can manually enable (or disable) the issuance of the client certificate u
    ​​​​sing the `--[no-]issue-client-certificate` flag.
    ​​​​WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using `--no-
    ​​​​enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag to suppress this warning.
    ​​​​WARNING: Starting in 1.12, default node pools in new clusters will have their legacy Compute Engine instance metadata endpoints disabled by default. To create a
    ​​​​ cluster with legacy instance metadata endpoints disabled in the default node pool, run `clusters create` with the flag `--metadata disable-legacy-endpoints=tru
    ​​​​e`.
    ​​​​WARNING: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
    ​​​​This will enable the autorepair feature for nodes. Please see https://cloud.google.com/kubernetes-engine/docs/node-auto-repair for more information on node auto
    ​​​​repairs.
    ​​​​Creating cluster k8s201908 in us-west1-a... Cluster is being deployed...⠏ 
    

(Back to slides )

Get example code

  1. Go to the https://github.com/William-Yeh/workshop-k8s201908 .

  2. Clone example project.

    ​​​​$ git clone https://github.com/William-Yeh/workshop-k8s201908.git
    

Lab # 1.0

  1. C#
  2. MVC

Lab # 2.0

  1. Add a Dockerfile.

Lab # 3.0

  1. 前後端分離。

  2. 前端 30000 port、後端 30080 port。

  3. Checkout to 3.0 tag.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 2.0)) - 14:48
    ​​​​(cmd)$ git checkout 3.0
    ​​​​Previous HEAD position was 89f2e7f 2.0: Dockerize the app with simple Dockerfile and docker-compose.yml.
    ​​​​HEAD is now at f7dc3e4 3.0: Separate frontend and backend into 2 distinct containers.
    
  4. Review files.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:48
    ​​​​(ins)$ tree .
    ​​​​.
    ​​​​├── LICENSE
    ​​​​├── README.md
    ​​​​├── TodoApi
    ​​​​│   ├── Controllers
    ​​​​│   │   └── TodoController.cs
    ​​​​│   ├── Dockerfile
    ​​​​│   ├── LICENSE
    ​​​​│   ├── Models
    ​​​​│   │   ├── TodoContext.cs
    ​​​​│   │   └── TodoItem.cs
    ​​​​│   ├── Program.cs
    ​​​​│   ├── Startup.cs
    ​​​​│   ├── TodoApi.csproj
    ​​​​│   ├── appsettings.Development.json
    ​​​​│   └── appsettings.json
    ​​​​├── TodoApi-original.zip
    ​​​​├── TodoFrontend
    ​​​​│   ├── Dockerfile
    ​​​​│   ├── index.html
    ​​​​│   ├── jquery-3.3.1.min.js
    ​​​​│   └── site.js
    ​​​​└── docker-compose.yml
    
    ​​​​4 directories, 18 files
    
  5. Run containers.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:48
    ​​​​(ins)$ docker-compose up -d
    ​​​​Creating network "workshop-k8s201908_default" with the default driver
    ​​​​Building todo-api
    ​​​​Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
    ​​​​ ---> 3af77ac73731
    ​​​​Step 2/13 : WORKDIR /app
    ​​​​ ---> Running in f430e0b20b52
    ​​​​Removing intermediate container f430e0b20b52
    ​​​​ ---> 8b7149f6bdcd
    ​​​​Step 3/13 : COPY *.csproj .
    ​​​​ ---> a349dbb180b8
    ​​​​Step 4/13 : RUN  dotnet restore
    ​​​​ ---> Running in ada285379fba
    ​​​​  Restore completed in 3.65 sec for /app/TodoApi.csproj.
    ​​​​Removing intermediate container ada285379fba
    ​​​​ ---> e638dde0c78d
    ​​​​Step 5/13 : COPY . .
    ​​​​ ---> 832aa52eb047
    ​​​​Step 6/13 : RUN  dotnet publish -o out
    ​​​​ ---> Running in 0541629e4e1d
    ​​​​Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
    ​​​​Copyright (C) Microsoft Corporation. All rights reserved.
    
    ​​​​  Restore completed in 61.12 ms for /app/TodoApi.csproj.
    ​​​​  TodoApi -> /app/bin/Debug/netcoreapp2.2/TodoApi.dll
    ​​​​  TodoApi -> /app/out/
    ​​​​Removing intermediate container 0541629e4e1d
    ​​​​ ---> ea17fcdd991a
    ​​​​Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
    ​​​​ ---> 3ee0429b27ad
    ​​​​Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
    ​​​​ ---> Running in 4eaf3256b79f
    ​​​​Removing intermediate container 4eaf3256b79f
    ​​​​ ---> b4a4070d93e4
    ​​​​Step 9/13 : ENV ASPNETCORE_URLS http://+:80
    ​​​​ ---> Running in 19a4868bcb30
    ​​​​Removing intermediate container 19a4868bcb30
    ​​​​ ---> 9a64e28f467f
    ​​​​Step 10/13 : EXPOSE 80
    ​​​​ ---> Running in 5c3038f9097c
    ​​​​Removing intermediate container 5c3038f9097c
    ​​​​ ---> 38331774d119
    ​​​​Step 11/13 : WORKDIR /app
    ​​​​ ---> Running in 9e33aaeb1e01
    ​​​​Removing intermediate container 9e33aaeb1e01
    ​​​​ ---> f0bb3fb67cc4
    ​​​​Step 12/13 : COPY --from=build /app/out ./
    ​​​​ ---> 69a3362e64c2
    ​​​​Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
    ​​​​ ---> Running in 4fd7f7a5be59
    ​​​​Removing intermediate container 4fd7f7a5be59
    ​​​​ ---> 6e5ddb8f2e3f
    ​​​​Successfully built 6e5ddb8f2e3f
    ​​​​Successfully tagged todoapi:3.0
    ​​​​WARNING: Image for service todo-api was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
    ​​​​Building todo
    ​​​​Step 1/5 : FROM busybox:1.30
    ​​​​1.30: Pulling from library/busybox
    ​​​​53071b97a884: Pull complete
    ​​​​Digest: sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
    ​​​​Status: Downloaded newer image for busybox:1.30
    ​​​​ ---> 64f5d945efcc
    ​​​​Step 2/5 : WORKDIR /app
    ​​​​ ---> Running in 0ae754b31362
    ​​​​Removing intermediate container 0ae754b31362
    ​​​​ ---> 169cf1e37654
    ​​​​Step 3/5 : COPY . .
    ​​​​ ---> b3accd7b6ee3
    ​​​​Step 4/5 : EXPOSE 80
    ​​​​ ---> Running in b67f2f80d0f3
    ​​​​Removing intermediate container b67f2f80d0f3
    ​​​​ ---> fdb878c03886
    ​​​​Step 5/5 : CMD ["busybox", "httpd", "-f", "-p", "80"]
    ​​​​ ---> Running in e901359151a3
    ​​​​Removing intermediate container e901359151a3
    ​​​​ ---> 524f3da6f6df
    ​​​​Successfully built 524f3da6f6df
    ​​​​Successfully tagged todofrontend:3.0
    ​​​​WARNING: Image for service todo was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
    ​​​​Creating workshop-k8s201908_todo-api_1 ... done
    ​​​​Creating workshop-k8s201908_todo_1     ... done
    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:49
    ​​​​(ins)$
    
  6. Remove current containers.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:54
    ​​​​(ins)$ docker-compose stop
    ​​​​Stopping workshop-k8s201908_todo_1     ... done
    ​​​​Stopping workshop-k8s201908_todo-api_1 ... done
    
    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:54
    ​​​​(ins)$ docker-compose rm -f
    ​​​​Going to remove workshop-k8s201908_todo_1, workshop-k8s201908_todo-api_1
    ​​​​Removing workshop-k8s201908_todo_1     ... done
    ​​​​Removing workshop-k8s201908_todo-api_1 ... done
    

Lab # 3.0 Review

  1. Architecture
  2. Main tasks
  3. Diff
  4. Tricks
  5. Quexxxxx

Lab # 4.0 Local Kubernetes

  1. git checkout 4.0

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 15:11
    ​​​​(ins)$ git checkout 4.0
    ​​​​Previous HEAD position was f7dc3e4 3.0: Separate frontend and backend into 2 distinct containers.
    ​​​​HEAD is now at 3a3502b 4.0: Support Kubernetes (locally).
    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:11
    ​​​​(ins)$
    
  2. git log

    ​​​​commit 3a3502b1ab772c9d5618f7142266371887cae124 (HEAD, tag: 4.0)
    ​​​​Author: William Yeh <william.pjyeh@gmail.com>
    ​​​​Date:   Wed Jul 10 11:15:57 2019 +0800
    
    ​​​​    4.0: Support Kubernetes (locally).
    
    ​​​​commit f7dc3e4f11af64d9ec5c7a3ad248b18ff9853cad (tag: 3.0)
    ​​​​Author: William Yeh <william.pjyeh@gmail.com>
    ​​​​Date:   Wed Jul 10 11:14:48 2019 +0800
    
    ​​​​    3.0: Separate frontend and backend into 2 distinct containers.
    
    ​​​​commit 89f2e7f76760257854aab0b1a0248e9fedee5f39 (tag: 2.0)
    ​​​​Author: William Yeh <william.pjyeh@gmail.com>
    ​​​​Date:   Wed Jul 10 11:13:54 2019 +0800
    
    ​​​​    2.0: Dockerize the app with simple Dockerfile and docker-compose.yml.
    
    ​​​​commit 64b77d3322668f21c64a5d387d7dd2a4b68ebd0e (tag: 1.0)
    ​​​​Author: William Yeh <william.pjyeh@gmail.com>
    ​​​​Date:   Wed Jul 10 11:12:29 2019 +0800
    
    ​​​​:
    
  3. git diff stat HEAD~1 HEAD

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:13
    ​​​​(ins)$ git diff --stat HEAD~1 HEAD
    ​​​​ README.md                     |  40 ++++++++++++++++---
    ​​​​ k8s-dashboard.md              |  38 ++++++++++++++++++
    ​​​​ k8s/kubernetes-dashboard.yaml | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ​​​​ k8s/todoapi-service.yml       |  52 +++++++++++++++++++++++++
    ​​​​ k8s/todofrontend-service.yml  |  52 +++++++++++++++++++++++++
    ​​​​ 5 files changed, 338 insertions(+), 6 deletions(-)
    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:13
    ​​​​(ins)$
    
  4. Review todofrontend-service.yml

Container: 將許多服務包進同一個容器中

kubernetes 架構:

  • Service
  • Deployment
  • Pod: 把多個 containers 綁在同個 IP、主機上。常見的例子有:
  • Backend service + redis。
  • Nginx + uWSGI +
  • Container

奇數選舉策略:最少一定要有 3 個

---

# 對應的版號。
apiVersion: v1

# 對應 K8s 的 Service 或 Deployment。
kind: Service                               # => Service

# 描述。
metadata:
  name: todofrontend
  labels:
    app: todo
    tier: frontend

# 真正的核心。
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30000
  selector:
    app: todo
    tier: frontend

---
apiVersion: apps/v1
kind: Deployment                            # ==> Deployment
metadata:
  name: todofrontend
  labels:
    app: todo
    tier: frontend

spec:
  replicas: 3
  selector:
    matchLabels:
      app: todo
      tier: frontend
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate

  template:   # pod definition              # ===> pod
    metadata:
      labels:
        app: todo
        tier: frontend
    spec:
      containers:                           # ====> container
        - name: todofrontend
          image: todofrontend:3.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
      #dnsPolicy: ClusterFirst
      #restartPolicy: Always

Deployment & Replica

Replicas = 3

  1. Deployment 包含 Pod 和 container。
  2. Pod 包含 container。

Make sure you're using local Kubernetes

https://github.com/William-Yeh/workshop-k8s201908/tree/4.0

  1. kubectl config view

Lab start

Create todo.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:40
(ins)$ kubectl create ns todo
namespace/todo created

Get status.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:40
(cmd)$ kubectl get ns
NAME              STATUS   AGE
default           Active   19m
kube-node-lease   Active   20m
kube-public       Active   20m
kube-system       Active   20m
todo              Active   36s

Build

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:41
(ins)$ docker-compose build
Building todo-api
Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
 ---> 3af77ac73731
Step 2/13 : WORKDIR /app
 ---> Running in 0dd4ba363418
Removing intermediate container 0dd4ba363418
 ---> a7e67b42ca56
Step 3/13 : COPY *.csproj .
 ---> 7dcba74980a0
Step 4/13 : RUN  dotnet restore
 ---> Running in fc08f13bae4c
  Restore completed in 996.91 ms for /app/TodoApi.csproj.
Removing intermediate container fc08f13bae4c
 ---> 121cf4a9687b
Step 5/13 : COPY . .
 ---> 78d96bf15d59
Step 6/13 : RUN  dotnet publish -o out
 ---> Running in 52a9ff3b903a
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 63.2 ms for /app/TodoApi.csproj.
  TodoApi -> /app/bin/Debug/netcoreapp2.2/TodoApi.dll
  TodoApi -> /app/out/
Removing intermediate container 52a9ff3b903a
 ---> 60b5a1d8b0e4
Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
 ---> 3ee0429b27ad
Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
 ---> Running in 215d38d42979
Removing intermediate container 215d38d42979
 ---> 0881e064ebd7
Step 9/13 : ENV ASPNETCORE_URLS http://+:80
 ---> Running in 16c32079f774
Removing intermediate container 16c32079f774
 ---> 4a488a38ad7a
Step 10/13 : EXPOSE 80
 ---> Running in 872944d628dc
Removing intermediate container 872944d628dc
 ---> 7a4504f487e4
Step 11/13 : WORKDIR /app
 ---> Running in 7d312d731af2
Removing intermediate container 7d312d731af2
 ---> 2a1ce265ad47
Step 12/13 : COPY --from=build /app/out ./
 ---> 60241e9eb65a
Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
 ---> Running in 804aa3123794
Removing intermediate container 804aa3123794
 ---> e62cc653f93a
Successfully built e62cc653f93a
Successfully tagged todoapi:3.0
Building todo
Step 1/5 : FROM busybox:1.30
1.30: Pulling from library/busybox
53071b97a884: Pull complete
Digest: sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
Status: Downloaded newer image for busybox:1.30
 ---> 64f5d945efcc
Step 2/5 : WORKDIR /app
 ---> Running in c09d9fb7e8ea
Removing intermediate container c09d9fb7e8ea
 ---> 11e21cf61811
Step 3/5 : COPY . .
 ---> e74c99765c36
Step 4/5 : EXPOSE 80
 ---> Running in 30041ed33d2c
Removing intermediate container 30041ed33d2c
 ---> 1af64117bba0
Step 5/5 : CMD ["busybox", "httpd", "-f", "-p", "80"]
 ---> Running in 7cf678322ccd
Removing intermediate container 7cf678322ccd
 ---> 2ae4f98e0e80
Successfully built 2ae4f98e0e80
Successfully tagged todofrontend:3.0
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:42

Before run, we can review pods status of default pool.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:43
(ins)$ kubectl get pods
No resources found.

Before run, we can review pods status of todo pool.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:43
(ins)$ kubectl get pods -n todo
No resources found.

Before run, we can review deployment status of todo pool.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:44
(cmd)$ kubectl get deploy -n todo
No resources found.

Run

apply todoapi-service to todo pool.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:42
(ins)$ kubectl apply -f k8s/todoapi-service.yml -n todo
service/todoapi created
deployment.apps/todoapi created
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:45
(ins)$ kubectl get svc -n todo
NAME      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
todoapi   NodePort   10.101.6.95   <none>        80:30080/TCP   3m50s
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:49
(ins)$ kubectl get deploy -n todo
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
todoapi   0/3     3            0           5m47s
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:50
(ins)$ kubectl get pods -n todo
NAME                       READY   STATUS             RESTARTS   AGE
todoapi-7c5c486947-5tw6t   0/1     ImagePullBackOff   0          6m34s
todoapi-7c5c486947-rz7h2   0/1     ErrImagePull       0          6m34s
todoapi-7c5c486947-z5wgk   0/1     ImagePullBackOff   0          6m34s

Try to delete one pod.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:50
(ins)$ kubectl delete pods todoapi-7c5c486947-rz7h2 -n todo
pod "todoapi-7c5c486947-rz7h2" deleted
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
(cmd)$ kubectl get pods -n todo
NAME                       READY   STATUS             RESTARTS   AGE
todoapi-7c5c486947-5tw6t   0/1     ImagePullBackOff   0          7m18s
todoapi-7c5c486947-wz2tj   0/1     ErrImagePull       0          7s
todoapi-7c5c486947-z5wgk   0/1     ImagePullBackOff   0          7m18s
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
(ins)$
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
(ins)$ kubectl apply -f k8s/todofrontend-service.yml -n todo
service/todofrontend created
deployment.apps/todofrontend created
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
(cmd)$ kubectl get svc -n todo
NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
todoapi        NodePort   10.101.6.95     <none>        80:30080/TCP   9m
todofrontend   NodePort   10.99.135.208   <none>        80:30000/TCP   54s
  1. 如有安裝 minikube,記得切回 docker-desktop!

  2. Get api status via curl.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(cmd)$ curl http://localhost:30080/api/todo
    ​​​​[{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(cmd)$ curl http://localhost:30080/api/todo   [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(cmd)$ curl http://localhost:30080/api/todo
    ​​​​[{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(cmd)$ curl http://localhost:30080/api/todo
    ​​​​[{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(cmd)$ curl http://localhost:30080/api/todo
    ​​​​[{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    ​​​​(ins)$
    

Lab # 5.0

https://github.com/William-Yeh/workshop-k8s201908/tree/5.0

  1. Checkout to 5.0 tag.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:15
    ​​​​(cmd)$ git checkout 5.0
    ​​​​Previous HEAD position was 3a3502b 4.0: Support Kubernetes (locally).
    ​​​​HEAD is now at 47f84f0 5.0: Support ConfigMap and naming convention.
    
  2. Remove todo namespace of 4.0 Lab.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:15
    ​​​​(ins)$ kubectl delete ns todo
    ​​​​namespace "todo" deleted
    
  3. Review changes.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:19
    ​​​​(ins)$ git diff --stat HEAD~1 HEAD
    ​​​​ README.md                    | 41 +++++++++++++++++++++++++++++++----------
    ​​​​ TodoFrontend/Dockerfile      | 11 ++++++++++-
    ​​​​ TodoFrontend/run.sh          | 16 ++++++++++++++++
    ​​​​ TodoFrontend/site.js         |  2 +-
    ​​​​ docker-compose.yml           |  2 +-
    ​​​​ k8s/config.local.yml         |  9 +++++++++
    ​​​​ k8s/todofrontend-service.yml | 14 ++++++++++++--
    ​​​​ 7 files changed, 80 insertions(+), 15 deletions(-)
    

TodoFrontend 的部分將 Dockerfile 的 CMD 改為執行 run.sh 這個 shell script ,主要的目的為取代程式碼中的環境變數

  • Replace with sed: {{xxx}} -> $xxx

Preparation

  1. Create the todo namespace.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:19
    ​​​​(ins)$ kubectl create ns todo
    ​​​​namespace/todo created
    
  2. foo

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:25
    ​​​​(ins)$ kubectl apply -f k8s/config.local.yml -n todo
    ​​​​configmap/config.local created
    
  3. foo

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:25
    ​​​​(ins)$ kubectl get configmaps -n todo
    ​​​​NAME           DATA   AGE
    ​​​​config.local   3      37s
    

Build

Build new 5.0 image.

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 1
(ins)$ docker-compose build
Building todo-api
Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
 ---> 3af77ac73731
Step 2/13 : WORKDIR /app
 ---> Using cache
 ---> a7e67b42ca56
Step 3/13 : COPY *.csproj .
 ---> Using cache
 ---> 7dcba74980a0
Step 4/13 : RUN  dotnet restore
 ---> Using cache
 ---> 121cf4a9687b
Step 5/13 : COPY . .
 ---> Using cache
 ---> 78d96bf15d59
Step 6/13 : RUN  dotnet publish -o out
 ---> Using cache
 ---> 60b5a1d8b0e4
Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
 ---> 3ee0429b27ad
Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
 ---> Using cache
 ---> 0881e064ebd7
Step 9/13 : ENV ASPNETCORE_URLS http://+:80
 ---> Using cache
 ---> 4a488a38ad7a
Step 10/13 : EXPOSE 80
 ---> Using cache
 ---> 7a4504f487e4
Step 11/13 : WORKDIR /app
 ---> Using cache
 ---> 2a1ce265ad47
Step 12/13 : COPY --from=build /app/out ./
 ---> Using cache
 ---> 60241e9eb65a
Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
 ---> Using cache
 ---> e62cc653f93a
Successfully built e62cc653f93a
Successfully tagged todoapi:3.0
Building todo
Step 1/8 : FROM busybox:1.30
 ---> 64f5d945efcc
Step 2/8 : WORKDIR /app
 ---> Using cache
 ---> 11e21cf61811
Step 3/8 : COPY . .
 ---> 98be11d67ac1
Step 4/8 : RUN chmod +x run.sh
 ---> Running in 85c55155993a
Removing intermediate container 85c55155993a
 ---> 8e7c83565fbb
Step 5/8 : ENV TODOAPI_HOST localhost
 ---> Running in b36f5fe1f734
Removing intermediate container b36f5fe1f734
 ---> 01d29407f4c6
Step 6/8 : ENV TODOAPI_PORT 30080
 ---> Running in 2386c465df0b
Removing intermediate container 2386c465df0b
 ---> 33b0c0a091ee
Step 7/8 : EXPOSE 80
 ---> Running in 7918de7a342d
Removing intermediate container 7918de7a342d
 ---> ceb4d9576c47
Step 8/8 : CMD ["./run.sh"]
 ---> Running in 9c0db2048fed
Removing intermediate container 9c0db2048fed
 ---> 8a51613c8863
Successfully built 8a51613c8863
Successfully tagged todofrontend:5.0
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:28
$

Run

[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 1
(cmd)$ kubectl apply -f k8s/todoapi-service.yml -n todo
service/todoapi created
deployment.apps/todoapi created
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:30
(ins)$ kubectl apply -f k8s/todofrontend-service.yml -n todo
service/todofrontend created
deployment.apps/todofrontend created
[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:30
(cmd)$ kubectl get svc -n todo
NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
todoapi        NodePort   10.111.165.42   <none>        80:30080/TCP   21s
todofrontend   NodePort   10.111.152.45   <none>        80:30000/TCP   7s

EnvFrom

目的在於可以將 configMap 注入 env 設定

https://github.com/William-Yeh/workshop-k8s201908/blob/5.0/k8s/todofrontend-service.yml#L51

    spec:
      containers:
        - name: todofrontend
          image: todofrontend:5.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
          envFrom:
            - configMapRef:
                name: config.local

LAB # 6.0

  1. Checkout to 6.0 tag.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:32
    ​​​​(cmd)$ git checkout 6.0
    ​​​​Previous HEAD position was 47f84f0 5.0: Support ConfigMap and naming convention.
    ​​​​HEAD is now at 0e7fd39 6.0: Support Kubernetes on the cloud (GKE for example) and use Skaffold to simplify the process.
    
  2. Diff.

    ​​​​[ jonny@unicorn ~/vcs/7.workshop/workshop-k8s201908 ] ((HEAD detached at 6.0)) - 16:41
    ​​​​(ins)$ git diff --stat HEAD~1 HEAD
    ​​​​ README.md                                | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
    ​​​​ docker-compose.yml                       |  23 -----------------
    ​​​​ gke-steps.md                             |  49 +++++++++++++++++++++++++++++++++++
    ​​​​ k8s/cloud/config.cloud.yml.tpl           |   9 +++++++
    ​​​​ k8s/cloud/fix-name.py                    |  93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ​​​​ k8s/cloud/todoapi-service.yml.tpl        |  55 +++++++++++++++++++++++++++++++++++++++
    ​​​​ k8s/cloud/todofrontend-service.yml.tpl   |  65 ++++++++++++++++++++++++++++++++++++++++++++++
    ​​​​ k8s/{ => local}/config.local.yml         |   0
    ​​​​ k8s/{ => local}/todoapi-service.yml      |   5 ++--
    ​​​​ k8s/{ => local}/todofrontend-service.yml |   5 ++--
    ​​​​ skaffold.yaml                            |  35 +++++++++++++++++++++++++
    ​​​​ 11 files changed, 405 insertions(+), 44 deletions(-)
    
  • 本次 LAB 是 手動選號 vs 自動選號 都會實作到。

Usage: the cloud case

https://github.com/William-Yeh/workshop-k8s201908/tree/6.0#usage-the-cloud-case

  1. 建成功的,就會看到 RUNNING 的狀態。

  2. 回頭記得砍掉已建好的環境,多練習個幾次!

Preparation

  1. Run the Workshop on GKE (Google Kubernetes Engine)

    https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/gke-steps.md

  2. Allocate a static external IP address for TODOAPI_HOST:

    ​​​​# reserve a new static external IP address for backend todoapi
    ​​​​% gcloud compute addresses create todoapi --region=us-west1 --network-tier=PREMIUM
    
    ​​​​# make sure the static external IP address has been allocated
    ​​​​% gcloud compute addresses list
    

    • todoapi ip address: 35.247.16.87
  3. We will replace the ip address at https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/k8s/cloud/todoapi-service.yml.tpl#L11 .

    ​​​​spec:
    ​​​​  type: LoadBalancer
    ​​​​  loadBalancerIP: TODOAPI_IP_ADDR  # external IP (ephemeral or static)
    ​​​​  ports:
    ​​​​    - name: http
    ​​​​      port: 80
    ​​​​      targetPort: 80
    ​​​​  selector:
    ​​​​    app: todo
    ​​​​    tier: backend
    
  4. 回頭練習完,記得把會收錢的 VPC IP 給拔掉。

  5. Fill in correct image names and static IP addresses by modifying the PROJECT_ID and TODOAPI_IP_ADDR symbols in manifest files, by either:

    ​​​​k8s/cloud/fix-name.py  PROJECT_ID  TODOAPI_IP_ADDR
    

  6. Create a todo namespace for this app:
    Create a todo namespace for this app:
    Load the ConfigMap content:

Build and Run

The Skaffold is like docker-compose for K8s.

https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/skaffold.yaml

  1. Use Skaffold to streamline the build-and-run process continuously:

    ​​​​# dev: LiveReload mode.
    ​​​​$ skaffold dev -p cloud --default-repo gcr.io/PROJECT_ID  -n todo
    

    若時間允許,可在 local 先體驗一下 Skaffold 的威力!再上 cloud 玩。

  2. Review the ip address.

    ​​​​$ kubectl get svc -n todo
    

Q&A

  1. K8s 在本機練習上,算穩定嗎?
  2. minikube 會比較穩定,但相對吃資源。

LAB # 6.0 Review

  1. Architecture
  2. Main tasks

LAB # 7.0 Canary release

  1. 新的 K8s 會使用 Istio 來跑 Canary release,比傳統 K8s 方法來得簡單好用。

  2. 09/11 K8s Summit 有人會分享這一塊。

END

Remove GKE cluster

  1. Delete the todo namespace.

  2. Release the static ip address. (1/3)

  3. Release the static ip address. (2/3)

  4. Release the static ip address. (3/3)

  5. Delete the Kubernetes clusters.

  6. DONE (1/2).

  7. DONE (2/2).

Select a repo