學習日志 211220 前情提要 配置 有狀態(tài)服務1
# K8s win10下minikube環(huán)境搭建 總結
- 安裝hyper-v
- 安裝minikube
? - 指定hyper-v
? - 指定新增的外部網(wǎng)絡虛擬交換機
- 安裝docker客戶端
- 在K8s上安裝私有docker倉庫
? - 生成證書
? - 共享目錄
- 開發(fā)示例Java應用 并部署到K8s上
? - Docker化
? - K8s描述文件
## 思路
- 因為要用微服務 所以要用K8s
- 因為要學K8s 所以要在windows上搭建學習環(huán)境
- 所以需要minikube
- 所以需要Hyper-v
- 因為K8s遵守docker image標準
- 所以java 應用需要docker化
- 所以需要Docker倉庫
- 因為不想用商用倉庫, 所以自己搭一個Docker倉庫
# Hyper-V
- 安裝 不再重復
# minikube安裝
- 環(huán)境變量 MINIKUBE_HOME
- 在Hyper-V上建 虛擬交換機, 選外部網(wǎng)絡, 命名為minikube
? - 名字可以自取, 下面指令中自己替換掉
- minikube start
? - `minikube start --vm-driver hyperv --hyperv-virtual-switch "minikube"`
? - 指定使用hyperv
? - 指定使用指定的虛擬交換機
- 后續(xù)不要再使用minikube start指令
? - 使用hyper-v的保存和啟動 指令來啟停環(huán)境
- 確認minikube虛擬機的IP, 應該形如 192.168.x.x
? - 記下這個IP, 后續(xù)稱之為 minikube_ip
## Q&A
- Q: 為什么要指定hyper-v
- A: 在裝了docker客戶端后, 不指定的話默認是用docker的, 但我實際用下來發(fā)現(xiàn)docker的不好用
- Q: 為什么要指定使用新增的虛擬交換機(外部IP)
- A: 因為這樣比較容易固定下minikube的IP 以便我們后續(xù)做docker私有倉庫等服務
? - 類似的服務可能需要使用私有證書, 而私有證書是發(fā)給IP的, 如果IP總是變, 則私有證書也要變來變去
# 安裝docker客戶端
- 略
# 在K8s上安裝私有docker倉庫
- 登錄minikube虛擬機 生成證書
? - ssh docker@minikube_ip
? - 默認密碼 tcuser
- 參考 https://www.linuxtechi.com/setup-private-docker-registry-kubernetes/
- 生成證書
- 部署 private register pods和services
- 修改windows機(開發(fā)機)的/etc/hosts解析 讓 k8s-master域名解析到 192.168.2.15
- 測試開發(fā)機訪問私有倉庫
? - 開啟開發(fā)機的docker客戶端
? - 把Java工程的鏡像上傳到新建的私有倉庫
? - docker push k8s-master:31320/springbootdemo:1.0.0
? - 參考Java工程Docker化一項
- 配置 K8s control plane 訪問私有倉庫
? - ssh minikube_ip
? - 修改 /etc/hosts 如 開發(fā)機
? - 復制證書
? - `sudo cp /opt/certs/registry.crt /etc/docker/certs.d/k8s-master:31320/ca.crt`
? - 如果目錄不存在就先建目錄
- 測試K8s control plane 訪問私有倉庫
? - ssh minikube_ip
? - docker pull k8s-master:31320/springbootdemo:1.0.0
# 開發(fā)Java應用并部署到K8s
- 開發(fā)Java spring boot應用
? - 引入web 開8080端口
? - 根路徑做個Rest RequestMApping
- Docker化
? - 編寫Dockerfile
? - 引入mvn docker plugin(可選) 執(zhí)行mvn dockerfile:build
? - 重新tag 改倉庫 tag
- 部署到K8s上
? - 編寫K8s.yaml描述文件
? - 描述deployment
? - 描述service
? - Apply -f
# 總結完畢
# 繼續(xù)學習 K8s configuration
- 不看k8s的官方文檔了 理由是其使用的 import javax.inject.Inject; 技術較舊
- 關鍵詞 k8s springboot configuration
- 參考 https://spring.io/guides/topicals/spring-on-kubernetes/
? - (可選) 引入actuator
? ? - 設置k8s.yaml healthy check 指向 actuator的healthy
? ? ? ```
? ? ? ? livenessProbe:
? ? ? ? ? httpGet:
? ? ? ? ? ? path: /actuator/health/liveness
? ? ? ? ? ? port: 8080
? ? ? ? readinessProbe:
? ? ? ? ? httpGet:
? ? ? ? ? ? path: /actuator/health/readiness
? ? ? ? ? ? port: 8080
? ? ? ? lifecycle:
? ? ? ? ? preStop:
? ? ? ? ? ? exec:
? ? ? ? ? ? ? command: ["sh", "-c", "sleep 10"]
? ? ? ```
? - 重點 Using ConfigMaps To Externalize Configuration
## 在k8s上創(chuàng)建configmap
- 創(chuàng)建一個properties文件
? - 例如 ./k8s/Application.properties
? - 里面寫一個springboot相關的配置項 比如
? ? ```
? ? server.shutdown=graceful
? ? management.endpoints.web.exposure.include=*
? ? ```
? - 使用如下命令創(chuàng)建k8s configmap
? ? - `kubectl create configmap gs-spring-boot-k8s --from-file=./k8s/Application.properties`
? - 校驗
? ? - `kubectl get configmap gs-spring-boot-k8s -o yaml`
- The last step is to mount this ConfigMap as a volume in the container
? - 把上述configmap做成一個容器上的文件路徑
? - 關鍵代碼
? ? ```
? ? 在containers.readnessProbe同級,加
? ? volumeMounts:
? ? ? - name: config-volume
? ? ? ? mountPath: /App/config
? ? 在containers: 同級 加
? ? volumes:
? ? ? - name: config-volume
? ? ? ? configMap:
? ? ? ? ? name: gs-spring-boot-k8s
? ? ```
? - 代碼解析
? ? - 給container指示, 要求其新開一個volumeMounts
? ? ? - 源 用名字指定? config-volume
? ? ? - 目標 路徑給 /App/config
? ? ? - 這里是 /App , 不是示例中的/workspace
? ? ? - 因為我們的Dockerfile的WORKDIR是/App
? ? - 創(chuàng)建名叫config-volume的volume
? ? ? - 命名 和上述volumeMounts要對應
? ? ? - 源 指定為 configMap
? ? ? - 名字就是之前創(chuàng)建的configMap的名字 即
? ? ? - gs-spring-boot-k8s
- 總結
? - configMap在k8s里是一種資源
? - 可以通過properties的格式創(chuàng)建
? - 可以mount給container的一個目錄
? - 這個目錄下會有一個叫做Applications.properties的文件
? ? - 這個文件名是默認的
? - 通過springboot的actuator去讀取展示
# 后續(xù)關于 Service Discovery and Load Balancing
- 只讀 不操作了
- 關鍵點
? > Kubernetes sets up DNS entries so that we can use the service ID (e.g. name-service) to make an HTTP request to the service without knowing the IP address of the pods. The Kubernetes service also load balances these requests between all the pods.
# k8s教程 configuring redis
- 讀一遍 不操作了
- 需要注意的就是 修改了configMap后 需要重建pod使其生效
? - 文檔中采取的重建pod的方法是
? - kubectl delete pod redis
? - 之后重新Apply k8s描述文件
- 其它需要注意的點
? - k8s描述文件可以是從網(wǎng)上下載下來的 即使用url
? - configMap的data可以直接寫, 不一定要from file
? - configMap可以映射成任何文件名 不一定是Applications.properties
? - 比如例子中被映射為了redis.conf
# Pos Security Admission(PSA)
- 是關于 pod能用什么版本的鏡像?
- 在PSA設置比較嚴格的情況下, deployment不能使用latest的tag的鏡像?
- 暫時用不到, 存疑
- 其它需要注意的點
? - 使用kind可以創(chuàng)建新集群
? - 創(chuàng)建集群時 需要指定一個集群image 如 kindest/node:v1.23.0
? - 可以讓kubectl匹配給新集群
? - 部分label的key有控制意義, 不能亂打
? - 比如 pod-security.kubernetes.io/enforce
## Apply Pod Security Standards at the Namespace Level
- 其它需要注意的點
? - 使用kubectl create ns xxx 來創(chuàng)建namespace
- 關于namespace的部分以后再說了
# Stateless Applications 無狀態(tài)應用
- 只讀 不操作
- 重點 創(chuàng)建服務時 指定 type=LoadBalancer
? ```
? kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
? ```
? - 感覺之前有服務負載沾著 原因就是service 的 type沒有設成LoadBalancer?
? - 這個依賴external load balancer
? - 參考 https://kubernetes.io/docs/tasks/access-Application-cluster/create-external-load-balancer/
? - K8s會負責和外部的load balancer通訊, 匯報內部ip變更之類的
? - 當外部load balancer提供好IP地址后, k8s會記錄下來
? ? - 如果沒有外部load balancer 則外部ip這里一直是pending
? - 所以正常情況下, 對外提供的服務不使用和control plane一樣的ip(minikube_ip)
? - 而是有自己的ip
- 其它關注的點
? - google云或amazon云 付費后提供kubectl可以使用的API
? - 如何讓kubectl和對應的線上租用的云匹配, 要根據(jù)對應的云提供商來設置
? ? - 估計就是下載個證書的事情
# Stateful Applications 有狀態(tài)應用
- 目標 建個mysql的數(shù)據(jù)庫
- 后續(xù)目標 Flink和ElasticSearch
## 前置任務
- HeadlessServices
? - 不需要load-balancing的服務
? - 沒有cluster IP
? - headless服務可以結合其它服務發(fā)現(xiàn)框架 不用k8s自己的服務發(fā)現(xiàn)實現(xiàn)
? - 參考 https://kubernetes.io/docs/concepts/services-networking/service/#headless-services
? - NodePort類型 關鍵就是在control plane上分配一個port, 路由給內部的服務
? - LoadBalancer類型 就是和外部load balancer協(xié)作, 申請一個獨立的IP, 再路由給內部的服務
- PersistentVolumes
? - Pods consume node resources and PVCs consume PV resources
- PersistentVolume Provisioning
## 創(chuàng)建一個StatefulSet
- 創(chuàng)建stateful set 替換(相當于)創(chuàng)建deployment
? - 創(chuàng)建 見示例 k8s/web.yaml
? - 檢查 `kubectl get statefulset web`
- stateful set里每個pod的創(chuàng)建是順序的 0創(chuàng)建好了再開始創(chuàng)建1
- stateful set里每個pod有獨立固定的id
? - 格式是 <statefulset名字>-<序號>
? - 這個也是每個節(jié)點的hostname
? - 用exec試一下
? - 內部DNS也生效了, 內部其它pod可以用nslookup找到web-0.nginx
? - 注意域名格式 web-0.nginx
# 檢查固定存儲的部分
- 檢查pvc
? - `kubectl get pvc -l App=nginx`
? - 此例使用是的動態(tài)pvc 自動創(chuàng)建了兩個pvc, 綁定到兩個pv上
- 上述兩個nginx服務各有1G的存儲, 不共享
? - 這個是有問題的, 應該搞成共享?
- 重新生成pod不影響存儲 pv還在那里
- 后續(xù) TODO Scaling a StatefulSet
# 總結
- StatefulSet
? - 固定DNS記錄 針對每一個pod
? ? - 相對, Stateless則是多個pod共享一個service的DNS解析記錄
? - 固定的存儲
? ? - 就算刪除pod重新創(chuàng)建, 存儲還是在的
? ? - 相對, Stateless則一般沒有存儲, 就算有日志什么的, 重新創(chuàng)建pod的話應該也丟失了