首頁>技術>

我是在騰訊雲CentOS的2臺伺服器上,在不翻牆的情況下使用kubeadm(最簡單的部署工具)搭建K8S叢集。其中,容器網路使用flannel,最終安裝好可以外網訪問的2.0.4版本的dashboard。不走彎路的話,4步即可完成:

1、準備系統環境

對這2臺新購的雲虛擬機器,都需要安裝docker:

yum install docker -y

安裝kubeadm前,需要先新增kubeadm的yum源:

cat > /etc/yum.repos.d/kubernetes.repo <<EOF[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0EOF

接著安裝目前最新版的kubeadm:

yum install kubeadm-1.20.1-0.x86_64

其中,kubeadm依賴的kubelet(K8S最核心的元件)、kubectl、kubernetes-cni網路外掛等會自動安裝。

最後啟用這2個服務:

systemctl enable kubelet.servicesystemctl start docker.service

騰訊雲主機預設已經將bridge-nf-call-iptables和ip_forward置為1,如果你的主機值為0,需要先將功能開啟:

sysctl -w net.bridge.bridge-nf-call-iptables=1sysctl -w net.ipv4.ip_forward=1

接著,針對部署K8S master節點的主機,還需要做些工作。由於騰訊雲預設的主機名並不是域名格式(不符合master節點要求),所以需要修改為你自定義的域名。這需要2個步驟:

將設計好的主機名寫入/etc/hostname檔案;將/etc/hosts中原主機名替換掉。2、部署master節點

kubeadm的init命令即可初始化以單節點部署的master。為了避免翻牆,我 使用了 registry.aliyuncs.com/google_containers 源 。雖然可以在kubeadm命令列中輸入源,比如:

kubeadm init --image-repository registry.aliyuncs.com/google_containers

但將其寫入資源編排檔案更易維護,我將其命名為kubeadm.yaml:

apiVersion: kubeadm.k8s.io/v1beta2imageRepository: registry.aliyuncs.com/google_containerskind: ClusterConfigurationkubernetesVersion: v1.20.1networking:  podSubnet: 10.244.0.0/16controllerManager:        ExtraArgs:                horizontal-pod-autoscaler-use-rest-clients: "true"                horizontal-pod-autoscaler-sync-period: "10s"                node-monitor-grace-period: "10s"

注意,這個編排檔案有4個細節:

10.244.0.0/16controllerManager

接著,使用編排檔案執行init命令:

kubeadm init --config ./kubeadm.yaml

注意,執行成功後kubeadm會返回類似下面的字樣:

Your Kubernetes control-plane has initialized successfully!

之後,還有2條重要的資訊:

1、後續kubectl預設控制叢集時,需要使用到CA金鑰,透過TLS協議保障通訊的安全性。我們要透過下面3行命令複製金鑰資訊,這樣,kubectl執行時會首先訪問當前使用者的.kube目錄,使用這些授權資訊訪問叢集:

mkdir -p $HOME/.kube  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config  sudo chown $(id -u):$(id -g) $HOME/.kube/config

2、之後新增worker節點時,要透過token才能保障安全性。因此,先把顯示的這行命令儲存下來:

kubeadm join 172.27.0.11:6443 --token xxxxxxxxxxxx \    --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxx
3.部署flannel網路

flannel網路需要指定IP地址段,在上一步中已經透過編排檔案設定為 10.244.0.0/16 。部署flannel只需要一行命令:

kubectl apply -f ./kube-flannel.yml

其中,由於原本可以直接下載的檔案必須翻牆,所以我把檔案內容列在下方,儲存為上述命令的kube-flannel.yml檔案(參見第5小節):

此時,呼叫get pods命令,可以看到master節點的元件和flannel網路都牌Running狀態:

[root@k8s]# kubectl get pods -n kube-systemNAME                                  READY   STATUS    RESTARTS   AGEcoredns-7f89b7bc75-g8c42              1/1     Running   0          118scoredns-7f89b7bc75-z2p7c              1/1     Running   0          118setcd-taohui.tech                      1/1     Running   0          2m6skube-apiserver-taohui.tech            1/1     Running   0          2m6skube-controller-manager-taohui.tech   1/1     Running   0          2m6skube-flannel-ds-kfzrg                 1/1     Running   0          13skube-proxy-qbdz5                      1/1     Running   0          118skube-scheduler-taohui.tech            1/1     Running   0          2m6s

接著,登入另一臺伺服器上,透過之前儲存的kubeadm join命令,將其加入K8S叢集。透過get nodes命令可以看到叢集中已有2個節點:

# kubectl get nodesNAME              STATUS   ROLES                  AGE   VERSIONtaohui.tech       Ready    control-plane,master   14h   v1.20.0workernode        Ready    <none>                 12h   v1.20.1

至此叢集部署成功!如果有引數錯誤需要修改,你也可以在reset後重新init叢集:

kubeadm reset
4.部署dashboard的

我們可以用以WEB頁面的視覺化dashboard,監控叢集的狀態。部署時同樣面臨翻牆和版本匹配的問題,這裡我將2個映象源替換後儲存為dashboard.yaml編排檔案(參見第6小節):

kubectl apply -f dashboard.yaml

執行成功後,你可以檢視到service:

# kubectl get svc -n kubernetes-dashboardNAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGEdashboard-metrics-scraper   ClusterIP   10.100.6.83     <none>        8000/TCP   13hkubernetes-dashboard        ClusterIP   10.99.243.226   <none>        443/TCP    13h

注意,dashboard預設不允許外網訪問。即使我們透過kubectl proxy允許外網訪問,但dashboard又只允許HTTPS訪問,這樣kubeadm init時自簽名的CA證書是不被瀏覽器承認的。我採用的方案是Nginx作為反向代理,使用Lets Encrypt提供的有效證書對外提供服務,再經由proxy_pass指令反向代理到kubectl proxy上,例如:

kubectl proxy --port=8888 --accept-hosts='^*$'

此時,本地可經由8888訪問到dashboard。再透過Nginx訪問它:

proxy_pass http://localhost:8888;

這樣,當在外網根據我的域名訪問如下URL:

https://mydomain/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login

就會展現2種登陸方式:

接下來採用token方式。首先要建立管理員帳戶:

cat <<EOF | kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: admin-user  namespace: kubernetes-dashboardEOF

執行完後,serviceaccount/admin-user使用者已經建立。接著,將使用者繫結已經存在的叢集管理員角色:

cat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: admin-userroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: admin-user  namespace: kubernetes-dashboardEOF

最後,獲取可使用者於訪問的token:

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

將token貼上到登入頁面,就可以看到dashboard了(下圖是node頁面):

5、用於部署flannel網路的資源編排檔案
---apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata:  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/defaultspec:  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: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: flannelrules:- 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: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: flannelroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: flannelsubjects:- kind: ServiceAccount  name: flannel  namespace: kube-system---apiVersion: v1kind: ServiceAccountmetadata:  name: flannel  namespace: kube-system---kind: ConfigMapapiVersion: v1metadata:  name: kube-flannel-cfg  namespace: kube-system  labels:    tier: node    app: flanneldata:  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/v1kind: DaemonSetmetadata:  name: kube-flannel-ds  namespace: kube-system  labels:    tier: node    app: flannelspec:  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      hostNetwork: true      priorityClassName: system-node-critical      tolerations:      - operator: Exists        effect: NoSchedule      serviceAccountName: flannel      initContainers:      - name: install-cni        image: quay.io/coreos/flannel:v0.13.1-rc1        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.13.1-rc1        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
6、用於部署dashboard的資源編排檔案dashboard.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: v1kind: Namespacemetadata:  name: kubernetes-dashboard---apiVersion: v1kind: ServiceAccountmetadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kubernetes-dashboard---kind: ServiceapiVersion: v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kubernetes-dashboardspec:  ports:    - port: 443      targetPort: 8443  selector:    k8s-app: kubernetes-dashboard---apiVersion: v1kind: Secretmetadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard-certs  namespace: kubernetes-dashboardtype: Opaque---apiVersion: v1kind: Secretmetadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard-csrf  namespace: kubernetes-dashboardtype: Opaquedata:  csrf: ""---apiVersion: v1kind: Secretmetadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard-key-holder  namespace: kubernetes-dashboardtype: Opaque---kind: ConfigMapapiVersion: v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard-settings  namespace: kubernetes-dashboard---kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kubernetes-dashboardrules:  # 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: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboardrules:  # 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/v1kind: RoleBindingmetadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kubernetes-dashboardroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: kubernetes-dashboardsubjects:  - kind: ServiceAccount    name: kubernetes-dashboard    namespace: kubernetes-dashboard---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: kubernetes-dashboardroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: kubernetes-dashboardsubjects:  - kind: ServiceAccount    name: kubernetes-dashboard    namespace: kubernetes-dashboard---kind: DeploymentapiVersion: apps/v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kubernetes-dashboardspec:  replicas: 1  revisionHistoryLimit: 10  selector:    matchLabels:      k8s-app: kubernetes-dashboard  template:    metadata:      labels:        k8s-app: kubernetes-dashboard    spec:      containers:        - name: kubernetes-dashboard          image: registry.cn-shanghai.aliyuncs.com/jieee/dashboard:v2.0.4          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: ServiceapiVersion: v1metadata:  labels:    k8s-app: dashboard-metrics-scraper  name: dashboard-metrics-scraper  namespace: kubernetes-dashboardspec:  ports:    - port: 8000      targetPort: 8000  selector:    k8s-app: dashboard-metrics-scraper---kind: DeploymentapiVersion: apps/v1metadata:  labels:    k8s-app: dashboard-metrics-scraper  name: dashboard-metrics-scraper  namespace: kubernetes-dashboardspec:  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: registry.cn-shanghai.aliyuncs.com/jieee/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: {}

來源:https://www.tuicool.com/articles/ZfUZneY

28
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 從開發者的角度初探Harmony