.Net微服務實戰之Kubernetes的搭建與使用
系列文章
- .Net微服務實戰之技術選型篇
- .Net微服務實戰之技術架構分層篇
- .Net微服務實戰之DevOps篇
- .Net微服務實戰之負載均衡(上)
-
.Net微服務實戰之CI/CD
前言
說到微服務就得扯到自動化運維,然後別人就不得不問你用沒用上K8S。K8S的門檻比Docker Compose、Docker Swarm高了不少,無論是概念上還是在實施搭建時。我自己也經過了多次的實踐,整理出一套順利部署的流程。
我這次搭建花了一共整整4個工作實踐與一個工作日寫部落格,中間有一個網路問題導致reset了叢集重新搭了一次,完成後結合了Jenkins使用,還是成就感滿滿的。如果對大家有用,還請點個推薦於關注。
基本概念
Kubectl
kubectl用於執行Kubernetes叢集命令的管理工具,Kubernetes kubectl 與 Docker 命令關係可以檢視這裡
http://docs.kubernetes.org.cn/70.html
Kubeadm
kubeadm 是 kubernetes 的叢集安裝工具,能夠快速安裝 kubernetes 叢集,相關命令有以下:
kubeadm init kubeadm join
Kubelet
kubelet是主要的節點代理,它會監視已分配給節點的pod,具體功能:
- 安裝Pod所需的volume。
- 下載Pod的Secrets。
- Pod中執行的 docker(或experimentally,rkt)容器。
- 定期執行容器健康檢查。
Pod
Pod是Kubernetes建立或部署的最小(最簡單)的基本單位,一個Pod代表叢集上正在執行的一個程序,它可能由單個容器或多個容器共享組成的資源。
一個Pod封裝一個應用容器(也可以有多個容器),儲存資源、一個獨立的網路IP以及管理控制容器執行方式的策略選項。
Pods提供兩種共享資源:網路和儲存。
網路
每個Pod被分配一個獨立的IP地址,Pod中的每個容器共享網路名稱空間,包括IP地址和網路埠。Pod內的容器可以使用localhost相互通訊。當Pod中的容器與Pod 外部通訊時,他們必須協調如何使用共享網路資源(如埠)。
儲存
Pod可以指定一組共享儲存volumes
Service
一個應用服務在Kubernetes中可能會有一個或多個Pod,每個Pod的IP地址由網路元件動態隨機分配(Pod重啟後IP地址會改變)。為遮蔽這些後端例項的動態變化和對多例項的負載均衡,引入了Service這個資源物件。
Kubernetes ServiceTypes 允許指定一個需要的型別的 Service,預設是 ClusterIP 型別。
Type 的取值以及行為如下:
- ClusterIP:通過叢集的內部 IP 暴露服務,選擇該值,服務只能夠在叢集內部可以訪問,這也是預設的 ServiceType。
- NodePort:通過每個 Node 上的 IP 和靜態埠(NodePort)暴露服務。NodePort 服務會路由到 ClusterIP 服務,這個 ClusterIP 服務會自動建立。通過請求 <NodeIP>:<NodePort>,可以從叢集的外部訪問一個 NodePort 服務。
- LoadBalancer:使用雲提供商的負載局衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務。
- ExternalName:通過返回 CNAME 和它的值,可以將服務對映到 externalName 欄位的內容(例如, foo.bar.example.com)。 沒有任何型別代理被建立,這隻有 Kubernetes 1.7 或更高版本的 kube-dns 才支援。
其他詳細的概念請移步到 http://docs.kubernetes.org.cn/227.html
物理部署圖
Docker-ce 1.19安裝
在所有需要用到kubernetes伺服器上安裝docker-ce
解除安裝舊版本 docker
yum remove docker docker-common docker-selinux dockesr-engine -y升級系統軟體
yum upgrade -y安裝必要的一些系統工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2新增docker-ce軟體源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo更新並安裝 docker-ce
yum makecache fast yum install docker-ce-19.03.12 -y新增docker國內映象源
vim /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"], "registry-mirrors" : [ "http://ovfftd6p.mirror.aliyuncs.com", "http://registry.docker-cn.com", "http://docker.mirrors.ustc.edu.cn", "http://hub-mirror.c.163.com" ], "insecure-registries" : [ "registry.docker-cn.com", "docker.mirrors.ustc.edu.cn" ], "debug" : true, "experimental" : true }
啟動服務
systemctl start docker systemctl enable docker
安裝kubernetes-1.18.3
所有需要用到kubernetes的伺服器都執行以下指令。
新增阿里kubernetes源cat <<EOF > /etc/yum.repos.d/kubernetes.repo安裝並啟動
[kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
yum install kubeadm-1.18.3 kubectl-1.18.3 kubelet-1.18.3
啟動kubelet
systemctl enable kubelet systemctl start kubelet在Master設定環境變數,在/etc/profile中配置
vim /etc/profile在最後新增如下配置
export KUBECONFIG=/etc/kubernetes/admin.conf
執行命令使其起效
source /etc/profile
初始化k8s叢集
在master節點(server-a)進行初始化叢集
開放埠
firewall-cmd --permanent --zone=public --add-port=6443/tcp firewall-cmd --permanent --zone=public --add-port=10250/tcp firewall-cmd --reload關閉swap
vim /etc/fstab #註釋swap那行 swapoff -a
設定iptables規則
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
初始化
kubeadm init --kubernetes-version=1.18.3 --apiserver-advertise-address=192.168.88.138 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.10.0.0/16 --pod-network-cidr=10.122.0.0/16 --ignore-preflight-errors=Swappod-network-cidr引數的為pod網段:,apiserver-advertise-address引數為本機IP。 如果中途執行有異常可以通過 kubeadm reset 後重新init。 初始化成功執行下面指令
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config檢視node和pod資訊
kubectl get node kubectl get pod --all-namespaces
安裝flannel元件
在master節點(server-a)安裝flannel元件
找個梯子下載kube-flannel.yml檔案
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
下載不了也沒關係,我複製給到大家:
--- apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: psp.flannel.unprivileged annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default spec: privileged: false volumes: - configMap - secret - emptyDir - hostPath allowedHostPaths: - pathPrefix: "/etc/cni/net.d" - pathPrefix: "/etc/kube-flannel" - pathPrefix: "/run/flannel" readOnlyRootFilesystem: false # Users and groups runAsUser: rule: RunAsAny supplementalGroups: rule: RunAsAny fsGroup: rule: RunAsAny # Privilege Escalation allowPrivilegeEscalation: false defaultAllowPrivilegeEscalation: false # Capabilities allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] defaultAddCapabilities: [] requiredDropCapabilities: [] # Host namespaces hostPID: false hostIPC: false hostNetwork: true hostPorts: - min: 0 max: 65535 # SELinux seLinux: # SELinux is unused in CaaSP rule: 'RunAsAny' --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: flannel rules: - apiGroups: ['extensions'] resources: ['podsecuritypolicies'] verbs: ['use'] resourceNames: ['psp.flannel.unprivileged'] - apiGroups: - "" resources: - pods verbs: - get - apiGroups: - "" resources: - nodes verbs: - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: flannel roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: flannel subjects: - kind: ServiceAccount name: flannel namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: flannel namespace: kube-system --- kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-system labels: tier: node app: flannel data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds-amd64 namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux - key: kubernetes.io/arch operator: In values: - amd64 hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.12.0-amd64 command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-amd64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds-arm64 namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux - key: kubernetes.io/arch operator: In values: - arm64 hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.12.0-arm64 command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-arm64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds-arm namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux - key: kubernetes.io/arch operator: In values: - arm hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.12.0-arm command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-arm command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds-ppc64le namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux - key: kubernetes.io/arch operator: In values: - ppc64le hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.12.0-ppc64le command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-ppc64le command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds-s390x namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux - key: kubernetes.io/arch operator: In values: - s390x hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.12.0-s390x command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-s390x command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfgView Code
先拉取依賴映象
docker pull quay.io/coreos/flannel:v0.12.0-amd64
把上面檔案儲存到伺服器然後執行下面命令
kubectl apply -f kube-flannel.yml
安裝dashboard
在master節點(server-a)安裝dashboard元件
繼續用梯子下載recommended.yml檔案
https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
沒梯子的可以複製下方原檔案
# Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: v1 kind: Namespace metadata: name: kubernetes-dashboard --- apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard --- kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: ports: - port: 443 targetPort: 8443 selector: k8s-app: kubernetes-dashboard --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-certs namespace: kubernetes-dashboard type: Opaque --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-csrf namespace: kubernetes-dashboard type: Opaque data: csrf: "" --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-key-holder namespace: kubernetes-dashboard type: Opaque --- kind: ConfigMap apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-settings namespace: kubernetes-dashboard --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard rules: # Allow Dashboard to get, update and delete Dashboard exclusive secrets. - apiGroups: [""] resources: ["secrets"] resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"] verbs: ["get", "update", "delete"] # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. - apiGroups: [""] resources: ["configmaps"] resourceNames: ["kubernetes-dashboard-settings"] verbs: ["get", "update"] # Allow Dashboard to get metrics. - apiGroups: [""] resources: ["services"] resourceNames: ["heapster", "dashboard-metrics-scraper"] verbs: ["proxy"] - apiGroups: [""] resources: ["services/proxy"] resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"] verbs: ["get"] --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard rules: # Allow Metrics Scraper to get metrics from the Metrics server - apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kubernetes-dashboard subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kubernetes-dashboard subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard --- kind: Deployment apiVersion: apps/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: kubernetes-dashboard template: metadata: labels: k8s-app: kubernetes-dashboard spec: containers: - name: kubernetes-dashboard image: kubernetesui/dashboard:v2.0.3 imagePullPolicy: Always ports: - containerPort: 8443 protocol: TCP args: - --auto-generate-certificates - --namespace=kubernetes-dashboard # Uncomment the following line to manually specify Kubernetes API server Host # If not specified, Dashboard will attempt to auto discover the API server and connect # to it. Uncomment only if the default does not work. # - --apiserver-host=http://my-address:port volumeMounts: - name: kubernetes-dashboard-certs mountPath: /certs # Create on-disk volume to store exec logs - mountPath: /tmp name: tmp-volume livenessProbe: httpGet: scheme: HTTPS path: / port: 8443 initialDelaySeconds: 30 timeoutSeconds: 30 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1001 runAsGroup: 2001 volumes: - name: kubernetes-dashboard-certs secret: secretName: kubernetes-dashboard-certs - name: tmp-volume emptyDir: {} serviceAccountName: kubernetes-dashboard nodeSelector: "kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule --- kind: Service apiVersion: v1 metadata: labels: k8s-app: dashboard-metrics-scraper name: dashboard-metrics-scraper namespace: kubernetes-dashboard spec: ports: - port: 8000 targetPort: 8000 selector: k8s-app: dashboard-metrics-scraper --- kind: Deployment apiVersion: apps/v1 metadata: labels: k8s-app: dashboard-metrics-scraper name: dashboard-metrics-scraper namespace: kubernetes-dashboard spec: replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: dashboard-metrics-scraper template: metadata: labels: k8s-app: dashboard-metrics-scraper annotations: seccomp.security.alpha.kubernetes.io/pod: 'runtime/default' spec: containers: - name: dashboard-metrics-scraper image: kubernetesui/metrics-scraper:v1.0.4 ports: - containerPort: 8000 protocol: TCP livenessProbe: httpGet: scheme: HTTP path: / port: 8000 initialDelaySeconds: 30 timeoutSeconds: 30 volumeMounts: - mountPath: /tmp name: tmp-volume securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1001 runAsGroup: 2001 serviceAccountName: kubernetes-dashboard nodeSelector: "kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule volumes: - name: tmp-volume emptyDir: {}View Code 第39行修改,埠範圍30000-32767
spec: type: NodePort ports: - port: 443 targetPort: 8443 nodePort: 30221 selector: k8s-app: kubernetes-dashboard
第137行開始,修改賬戶許可權,主要三個引數,kind: ClusterRoleBinding,roleRef-kind: ClusterRole,roleRef-name: cluster-admin
--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard ---
儲存到伺服器後執行以下命令
kubectl apply -f recommended.yaml
等待一段時間啟動成功後,https://ip+nodePort,檢視UI
Token通過下面指令獲取
kubectl -n kubernetes-dashboard get secret kubectl describe secrets -n kubernetes-dashboard kubernetes-dashboard-token-kfcp2 | grep token | awk 'NR==3{print $2}'
加入Worker節點
在server-b與server-c執行下面操作
把上面init後的那句join拷貝過來,如果忘記了可以在master節點執行下面指令:
kubeadm token list openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
通過返回的資料拼裝成下面指令
kubeadm join 192.168.88.138:6443 --token 2zebwy.1549suwrkkven7ow --discovery-token-ca-cert-hash sha256:c61af74d6e4ba1871eceaef4e769d14a20a86c9276ac0899f8ec6b08b89f532b
檢視節點資訊
kubectl get node
部署Web應用
在master節點(sever-a)執行下面操作
部署應用前建議有需要的朋友到【.Net微服務實戰之CI/CD】看看如何搭建docker私有倉庫,後面需要用到,搭建後私有庫後執行下面指令
kubectl create secret docker-registry docker-registry-secret --docker-server=192.168.88.141:6000 --docker-username=admin --docker-password=123456789
docker-server就是docker私有倉庫的地址
下面是yaml模板,注意imagePullSecrets-name與上面的命名的一致,其餘的可以檢視yaml裡的註釋
apiVersion: apps/v1 kind: Deployment # Deployment為多個Pod副本 metadata: name: testdockerswarm-deployment labels: app: testdockerswarm-deployment spec: replicas: 2 # 例項數量 selector: matchLabels: # 定義該部署匹配哪些Pod app: testdockerswarm minReadySeconds: 3 # 可選,指定Pod可以變成可用狀態的最小秒數,預設是0 strategy: type: RollingUpdate # 部署策略型別,使用RollingUpdate可以保證部署期間服務不間斷 rollingUpdate: maxUnavailable: 1 # 部署時最大允許停止的Pod數量 maxSurge: 1 # 部署時最大允許建立的Pod數量 template: # 用來指定Pod的模板,與Pod的定義類似 metadata: labels: # Pod標籤,與上面matchLabels對應 app: testdockerswarm spec: imagePullSecrets: - name: docker-registry-secret containers: - name: testdockerswarm image: 192.168.88.141:6000/testdockerswarm imagePullPolicy: Always # Always每次拉去新映象 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: testdockerswarm-service labels: name: testdockerswarm-service spec: selector: app: testdockerswarm #與template-labels引數pod標籤一致 ports: - protocol: TCP port: 80 #clusterIP開放的埠 targetPort: 80 #container開放的埠,與containerPort一致 nodePort: 31221 # 所有的節點都會開放此埠,此埠供外部呼叫。 type: NodePortView Code
把yaml檔案儲存到伺服器後執行下面命令
kubectl create -f testdockerswarm.yml
整個搭建部署的過程基本上到這裡結束了。
訪問
可以通過指令kubectl get service得到ClusterIP,分別在server-c和sever-b執行curl 10.10.184.184
也可以通過執行kubectl get pods -o wide得到pod ip,在server-c執行curl 10.122.2.5 和 server-b執行curl 10.122.1.7
也可以在外部訪問 server-c和server-b的 ip + 31221
如果節點有異常可以通過下面指令排查
journalctl -f -u kubelet.service | grep -i error -C 500
如果Pod無法正常running可以通過下面指令檢視
kubectl describe pod testdockerswarm-deployment-7bc647d87d-qwvzm