---
# System prepended metadata

title: Kubernetes

---

# Kubernetes
* Frame: K8s cluster - Node pools - Nodes (VM) - Pods (部署服務在上面，運作的最小單位，由deployment管理) - Containers (VM, image run 起來的時候要輸入甚麼指令)
* microservice: 功能被切開的一個一個微服務
* docker hub: 放image的地方，可以直接pull下來
* container: 磁碟(disk)虛擬化
* Node:
    * Master node: api server 所在的node
    * Worker node: pod 所在的node
    * life cycle: pending, initial, running, error, crush
* RBAC (role based access control): 
    * namespace: 在不同的namespace上有不同的權限，也可以看到不同的物件
    * role: 權限的集合
    * rolebinding: 
    
* quick start: https://cloud.google.com/kubernetes-engine/docs/quickstart#local-shell
    Trouble shooting:
    * gcloud init fail: open the login page in chrome instead of safari 
    * gcloud command not found: 
        * vi ~/.zshrc
        * add "source ~/.bash_profile"
        * source ~/.zshrc
        * suppose to work!
            
* [k8s document](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#-strong-api-overview-strong-)

* deployment:
    * 可以指定要部署到哪個pool，他會在某個node上面做事(pod 會分散在不同的node上面)
    * 一個pod 掛掉，deployment 會再長出新的
    * pod 沒開成功，deployment 會一直自動restart
    * deployment會自動分流，同個服務會由不同pod開啟

* kubectl commands:
    * get nodes: 顯示所有node名稱
    * create -f xxx.yaml: 部署東西上去(service或deployment)
    * apply -f xxx.yaml: 更新已部署東西(service或deployment)
    * get deployment.apps: 開pod
    * get pods: 找到所有的pod
    * delete -f xxx.yaml: 卸載deployment (pods也一起被刪了)
    * exec -it podname bash: 進到pod 裡面
    * get all: deployment, pod 之類的東西全部列出來
    * get pods -n namespace: 到一個namespace把裡面的pod列出來
    * get persistentvolumes: 列出PV
* [kubectx & kubens](https://github.com/ahmetb/kubectx#installation): Power tools for kubectl
## deployment 部署服務:
deployment.yaml
```
apiVersion: apps/v1
kind: Deployment #這是甚麼物件
metadata:
  name: yujie 
spec:
  replicas: 3 #開3個pod
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx  #service 要對到這個
    spec: # node的spec 可以加很多個container
      containers:
        - name: nginx
          image: nginx:latest
          resources: #container要用多少資源(上限與下限) 
              requests:
                  cpu: 1
                  memory: 123M
                  
          ports:
            - containerPort: 80
          nodeSelector: # 指定pod要放在哪個node上面(沒設定的話他會亂跑)
            - nodeCluster: darcy
```

service.yaml
```
apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
```
* 查看服務狀態

![](https://i.imgur.com/eicwlSO.png)
提供服務的pod裡可以看到pod run 在哪個節點上

## Statefulset
* 也是一個控制pod的物件
* storage 的部份一定要綁定 PVC，並綁定到特定的 StorageClass or 預先配置好的 PersistentVolume，確保 pod 被刪除後資料依然存在 
* 生出來的pod和PV會用ordered index 來命名(例如replica=3, pod 的名字就是xx-0, xx-1, xx-2)，當某個pod因故無法運作時，會再長出新的，有一樣名字的pod
* 每個pod都會掛一個自己的pv，有三個replica就會有三個pv
statefulset.yaml
```
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: hyperledger-fabric
  name: name
  namespace: fabric-tls
spec:
  selector:
    matchLabels:
      app: name
  serviceName: "service" #一定要寫不然會error
  template:
    metadata:
      labels:
        app: name
    spec:
        container ...
  volumeClaimTemplates:
    - metadata:
        name: pv
      spec:
        accessModes:
          - "ReadWriteOnce"
        resources:
          requests:
            storage: 1Gi
```
## 建立PV(Persistence Volume)
* 一個目錄且包含在 Pod 內獨立存活在容器外，當pod 被刪掉或crash掉時，pv不會被刪掉，所以可以保存不想被刪掉的東西
* PVC: 要一塊PV
* 如何建立: in *pvc.yaml*
```
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: fabric-tls
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi   #要求 1G 容量
```
* pod 綁定PV: in *deployment.yaml*, add
```
volumes:
    - name: pv
      persistentVolumeClaim:
        claimName: pvname #綁定名為pvname的pv
```

## 建立 Secret
* 把秘密資料的檔案放到secret 物件中，當pod 開啟的時候就能將此檔案讀到container 裡
* create secret: `kubectl create secret generic <secret name> --from-file=<file name> -n <namespace>`
* deploy pod and load secret: in *deploy.yaml*
```
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo" #secret 傳進來之後會存在container 的這個路徑內
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
```
