关于kubernetes:KubernetesStatefulSetPVPVC

StatefulSet适应场景: [x] 稳固且惟一的网络标识符[x] 稳固且长久的存储[x] 有序,优雅的部署和扩大[x] 有序,优雅的删除和终止[x] 有序而主动的滚动更新通用的StatefulSet形成: [x] Headless Service[x] StatefulSet[x] volumeClaimTemplate构建NFS文件系统装置NFS文件系统$ yum install -y nfs-common nfs-utils rpcbind$ mkdir /nfsdata /nfs1$ chmod 666 /nfsdata$ chown nfsnobody /nfsdata$ cat /etc/exports/data/nfs1 *(rw,no_root_squash,no_all_squash,sync)/data/nfs2 *(rw,no_root_squash,no_all_squash,sync)$ systemctl start rpcbind$ systemctl start nfs# 在kubernetes节点或者是minikube主机上用工具挂载测试$ sudo mount -t nfs 172.16.56.138:/data/nfs1 /data$ ls /dataindex.html StatefulSet/PV/PVC实战创立PV$ cat nfs-pv.yaml apiVersion: v1kind: PersistentVolumemetadata: name: nfspv1spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /data/nfs1 server: 172.16.56.138 $ kubectl apply -f nfs-pv.yaml$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnfspv1 10Gi RWO Retain Available nfs 5s ...

July 29, 2020 · 2 min · jiezi

关于kubernetes:KubernetesStatefulSetPVPVC

StatefulSet适应场景: [x] 稳固且惟一的网络标识符[x] 稳固且长久的存储[x] 有序,优雅的部署和扩大[x] 有序,优雅的删除和终止[x] 有序而主动的滚动更新通用的StatefulSet形成: [x] Headless Service[x] StatefulSet[x] volumeClaimTemplate构建NFS文件系统装置NFS文件系统$ yum install -y nfs-common nfs-utils rpcbind$ mkdir /nfsdata /nfs1$ chmod 666 /nfsdata$ chown nfsnobody /nfsdata$ cat /etc/exports/data/nfs1 *(rw,no_root_squash,no_all_squash,sync)/data/nfs2 *(rw,no_root_squash,no_all_squash,sync)$ systemctl start rpcbind$ systemctl start nfs# 在kubernetes节点或者是minikube主机上用工具挂载测试$ sudo mount -t nfs 172.16.56.138:/data/nfs1 /data$ ls /dataindex.html StatefulSet/PV/PVC实战创立PV$ cat nfs-pv.yaml apiVersion: v1kind: PersistentVolumemetadata: name: nfspv1spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /data/nfs1 server: 172.16.56.138 $ kubectl apply -f nfs-pv.yaml$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnfspv1 10Gi RWO Retain Available nfs 5s ...

July 29, 2020 · 2 min · jiezi

关于kubernetes:如何使用Istio-16管理多集群中的微服务

如果你正在一家典型的企业里工作,须要与多个团队一起工作,并为客户提供一个独立的软件,组成一个应用程序。你的团队遵循微服务架构,并领有由多个Kubernetes集群组成的宽泛基础设施。 因为微服务散布在多个集群中,你须要设计一个解决方案来集中管理所有微服务。侥幸的是,你正在应用Istio,提供这个解决方案只不过是另一个配置的变动。 像Istio这样的服务网格技术能够帮忙你平安地发现和连贯散布在多个集群和环境中的微服务。明天咱们来讨论一下应用Istio治理托管在多个Kubernetes集群中的微服务。 架构阐明Istio应用以下组件提供跨集群服务发现: Istio CoreDNS:每个Istio管制立体都有一个CoreDNS。Istio应用它来发现全局范畴上定义的服务。例如,如果一个托管在集群1上的微服务须要连贯到另一个托管在集群2上的微服务,你须要为运行在集群2上的微服务在Istio CoreDNS上做一个全局条目。Root CA:因为Istio须要在不同集群上运行的服务之间建设mTLS连贯,因而须要应用共享的Root CA为两个集群生成两头CA证书。这就在不同集群上运行的微服务之间建设了信赖,因为两头CA共享同一个Root CA。Istio Ingress网关:集群间的通信通过Ingress网关进行,服务之间没有间接连贯。因而,你要确保Ingress网关是可发现的,并且所有集群都能够连贯到它。 服务发现Istio应用以下步骤来促成服务发现: 集群上都有雷同的管制立体,以促成高可用性。Kube DNS与Istio CoreDNS为支点,以提供全局服务发现。用户通过Istio CoreDNS中的ServiceEntries定义近程服务的路由,格局为name.namespace.global。源sidecar应用全局CoreDNS条目将流量路由到指标Istio Ingress网关。指标 Istio Ingress 网关将流量路由到正确的微服务 pod。后期筹备 本文假如你曾经对Kubernetes以及Istio的工作原理有一个根本的理解。如果你想理解Istio 1.5和1.6的具体内容,点击此处即可查看相干视频。为了可能跟上咱们接下来的演示,请确保: 你有至多两个Kubernetes集群,Kubernetes的版本为1.14、1.15或1.16你领有在集群内装置和配置Istio的权限你在两个Kubernetes集群上都有集群管理权限。Ingress网关可通过网络负载均衡器或相似配置连贯到其余集群。扁平网络是不必要的。装置Istio在两个集群上,应用以下命令装置Istio 1.6.1: curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.1 sh -cd istio-1.6.1export PATH=$PWD/bin:$PATH因为咱们须要用共享的根证书生成的两头证书来启动咱们的Istio服务网格,所以应用两头证书创立一个secret。 在这个例子中,咱们应用提供的样本证书。然而,我不倡议你在生产中应用这些证书,因为它们个别都是可轻松获取的,而且是家喻户晓的。最好是应用你的组织的Root CA来生成两头CA证书。 在两个集群上运行以下命令来应用样本证书。如果你应用的是你的证书,请替换实用的文件门路。 kubectl create namespace istio-systemkubectl create secret generic cacerts -n istio-system \ --from-file=samples/certs/ca-cert.pem \ --from-file=samples/certs/ca-key.pem \ --from-file=samples/certs/root-cert.pem \ --from-file=samples/certs/cert-chain.pemsecret/cacerts created因为咱们须要装置Istio进行多集群设置,所以在两个集群上应用提供的Istio多集群网关manifest文件。 $ istioctl manifest apply -f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-gateways.yaml- Applying manifest for component Base...✔ Finished applying manifest for component Base.- Applying manifest for component Pilot...✔ Finished applying manifest for component Pilot. Waiting for resources to become ready...- Applying manifest for component AddonComponents...- Applying manifest for component IngressGateways...- Applying manifest for component EgressGateways...✔ Finished applying manifest for component EgressGateways.✔ Finished applying manifest for component IngressGateways.✔ Finished applying manifest for component AddonComponents.✔ Installation complete配置KubeDNS下一步是将DNS解析从Kube DNS联邦到Istio CoreDNS。让咱们通过为kube-dns定义一个ConfigMap来配置一个存根域。在两个集群上利用以下manifest: ...

July 28, 2020 · 2 min · jiezi

关于kubernetes:KubernetesVolume存储卷实践

VolumneemptyDirhostPath长期存储卷emptyDiremptyDir随着pod生命周期完结而完结$ cat vol-emptydir.yamlapiVersion: v1kind: Podmetadata: name: vol-emptydir-podspec: volumes: - name: html emptyDir: {} containers: - name: nginx image: nginx:1.12-alpine volumeMounts: - name: html mountPath: /usr/share/nginx/html - name: pagegen image: alpine volumeMounts: - name: html mountPath: /html command: ["/bin/sh", "-c"] args: - while true; do echo $(hostname) $(date) >> /html/index.html; sleep 10; done# emptyDir存储卷基于RAM举例,可用来做高速缓存 volumes: - name: cache emptyDir: medium: Memory$ kubectl create -f vol-emptydir.yaml$ kubectl delete pod vol-emptydir-pod节点存储卷hostPath将数据存在node节点磁盘上# 将工作节点的目录挂载至pod中$ cat vol-hostpath.yamlapiVersion: v1kind: Podmetadata: name: test-pdspec: containers: - image: myapp:v1 name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: path: /data type: Directory$ kubectl apply -f vol-hostpath.yaml# 查看pod中的容器$ kubectl exec -ti test-pd -- sh# date >> test.txt# more test.txtSun Apr 19 13:49:03 UTC 2020# 查看k8s节点k8s-node$ cat /data/test.txtSun Apr 19 13:49:03 UTC 2020

July 27, 2020 · 1 min · jiezi

关于kubernetes:KubernetesVolume存储卷实践

VolumneemptyDirhostPath长期存储卷emptyDiremptyDir随着pod生命周期完结而完结$ cat vol-emptydir.yamlapiVersion: v1kind: Podmetadata: name: vol-emptydir-podspec: volumes: - name: html emptyDir: {} containers: - name: nginx image: nginx:1.12-alpine volumeMounts: - name: html mountPath: /usr/share/nginx/html - name: pagegen image: alpine volumeMounts: - name: html mountPath: /html command: ["/bin/sh", "-c"] args: - while true; do echo $(hostname) $(date) >> /html/index.html; sleep 10; done# emptyDir存储卷基于RAM举例,可用来做高速缓存 volumes: - name: cache emptyDir: medium: Memory$ kubectl create -f vol-emptydir.yaml$ kubectl delete pod vol-emptydir-pod节点存储卷hostPath将数据存在node节点磁盘上# 将工作节点的目录挂载至pod中$ cat vol-hostpath.yamlapiVersion: v1kind: Podmetadata: name: test-pdspec: containers: - image: myapp:v1 name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: path: /data type: Directory$ kubectl apply -f vol-hostpath.yaml# 查看pod中的容器$ kubectl exec -ti test-pd -- sh# date >> test.txt# more test.txtSun Apr 19 13:49:03 UTC 2020# 查看k8s节点k8s-node$ cat /data/test.txtSun Apr 19 13:49:03 UTC 2020

July 27, 2020 · 1 min · jiezi

关于kubernetes:KubernetesIngress实践

IngressIngress-nginx用来做http代理,能够实现服务对外公布,采纳service的tcp须要更多的ip和端口 部署ingress的controller# 下载ingress contronller的部署文件$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml--2020-07-25 21:00:01-- https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml正在解析主机 raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.192.133, 151.101.64.133, 151.101.0.133, ...正在连接 raw.githubusercontent.com (raw.githubusercontent.com)|151.101.192.133|:443... 已连贯。已收回 HTTP 申请,正在期待回应... 200 OK长度:18133 (18K) [text/plain]正在保留至: “deploy.yaml”deploy.yaml 100%[==================================================>] 17.71K --.-KB/s 用时 0.05s 2020-07-25 21:00:01 (389 KB/s) - 已保留 “deploy.yaml” [18133/18133])下载后须要批改一些Service的type类型为NodePort,默认文件用的balancer# Source: ingress-nginx/templates/controller-service.yamlapiVersion: v1kind: Servicemetadata: labels: helm.sh/chart: ingress-nginx-2.11.1 app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/version: 0.34.1 app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginxspec: type: NodePort externalTrafficPolicy: Local ports: - name: http port: 80 nodePort: 30080 protocol: TCP targetPort: http - name: https port: 443 nodePort: 30443 protocol: TCP targetPort: https selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller# 执行ingress contronller部署$ kubectl apply -f deploy.yaml namespace/ingress-nginx createdserviceaccount/ingress-nginx createdconfigmap/ingress-nginx-controller createdclusterrole.rbac.authorization.k8s.io/ingress-nginx createdclusterrolebinding.rbac.authorization.k8s.io/ingress-nginx createdrole.rbac.authorization.k8s.io/ingress-nginx createdrolebinding.rbac.authorization.k8s.io/ingress-nginx createdservice/ingress-nginx-controller-admission createdservice/ingress-nginx-controller createddeployment.apps/ingress-nginx-controller createdvalidatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission createdclusterrole.rbac.authorization.k8s.io/ingress-nginx-admission createdclusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission createdjob.batch/ingress-nginx-admission-create createdjob.batch/ingress-nginx-admission-patch createdrole.rbac.authorization.k8s.io/ingress-nginx-admission createdrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission createdserviceaccount/ingress-nginx-admission created# 查看ingress-nginx命名空间下所创立的资源$kubectl get all -n ingress-nginxNAME READY STATUS RESTARTS AGEpod/ingress-nginx-admission-create-fvph7 0/1 Completed 0 5m46spod/ingress-nginx-admission-patch-gr48z 0/1 Completed 1 5m46spod/ingress-nginx-controller-c96557986-9rw9m 1/1 Running 0 5m56sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/ingress-nginx-controller NodePort 10.107.249.8 <none> 80:30080/TCP,443:30443/TCP 5m56sservice/ingress-nginx-controller-admission ClusterIP 10.104.5.150 <none> 443/TCP 5m56sNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/ingress-nginx-controller 1/1 1 1 5m56sNAME DESIRED CURRENT READY AGEreplicaset.apps/ingress-nginx-controller-c96557986 1 1 1 5m56sNAME COMPLETIONS DURATION AGEjob.batch/ingress-nginx-admission-create 1/1 2s 5m56sjob.batch/ingress-nginx-admission-patch 1/1 3s 5m56s ...

July 25, 2020 · 2 min · jiezi

关于kubernetes:KubernetesIngress实践

IngressIngress-nginx用来做http代理,能够实现服务对外公布,采纳service的tcp须要更多的ip和端口 部署ingress的controller# 下载ingress contronller的部署文件$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml--2020-07-25 21:00:01-- https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml正在解析主机 raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.192.133, 151.101.64.133, 151.101.0.133, ...正在连接 raw.githubusercontent.com (raw.githubusercontent.com)|151.101.192.133|:443... 已连贯。已收回 HTTP 申请,正在期待回应... 200 OK长度:18133 (18K) [text/plain]正在保留至: “deploy.yaml”deploy.yaml 100%[==================================================>] 17.71K --.-KB/s 用时 0.05s 2020-07-25 21:00:01 (389 KB/s) - 已保留 “deploy.yaml” [18133/18133])下载后须要批改一些Service的type类型为NodePort,默认文件用的balancer# Source: ingress-nginx/templates/controller-service.yamlapiVersion: v1kind: Servicemetadata: labels: helm.sh/chart: ingress-nginx-2.11.1 app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/version: 0.34.1 app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginxspec: type: NodePort externalTrafficPolicy: Local ports: - name: http port: 80 nodePort: 30080 protocol: TCP targetPort: http - name: https port: 443 nodePort: 30443 protocol: TCP targetPort: https selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller# 执行ingress contronller部署$ kubectl apply -f deploy.yaml namespace/ingress-nginx createdserviceaccount/ingress-nginx createdconfigmap/ingress-nginx-controller createdclusterrole.rbac.authorization.k8s.io/ingress-nginx createdclusterrolebinding.rbac.authorization.k8s.io/ingress-nginx createdrole.rbac.authorization.k8s.io/ingress-nginx createdrolebinding.rbac.authorization.k8s.io/ingress-nginx createdservice/ingress-nginx-controller-admission createdservice/ingress-nginx-controller createddeployment.apps/ingress-nginx-controller createdvalidatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission createdclusterrole.rbac.authorization.k8s.io/ingress-nginx-admission createdclusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission createdjob.batch/ingress-nginx-admission-create createdjob.batch/ingress-nginx-admission-patch createdrole.rbac.authorization.k8s.io/ingress-nginx-admission createdrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission createdserviceaccount/ingress-nginx-admission created# 查看ingress-nginx命名空间下所创立的资源$kubectl get all -n ingress-nginxNAME READY STATUS RESTARTS AGEpod/ingress-nginx-admission-create-fvph7 0/1 Completed 0 5m46spod/ingress-nginx-admission-patch-gr48z 0/1 Completed 1 5m46spod/ingress-nginx-controller-c96557986-9rw9m 1/1 Running 0 5m56sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/ingress-nginx-controller NodePort 10.107.249.8 <none> 80:30080/TCP,443:30443/TCP 5m56sservice/ingress-nginx-controller-admission ClusterIP 10.104.5.150 <none> 443/TCP 5m56sNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/ingress-nginx-controller 1/1 1 1 5m56sNAME DESIRED CURRENT READY AGEreplicaset.apps/ingress-nginx-controller-c96557986 1 1 1 5m56sNAME COMPLETIONS DURATION AGEjob.batch/ingress-nginx-admission-create 1/1 2s 5m56sjob.batch/ingress-nginx-admission-patch 1/1 3s 5m56s ...

July 25, 2020 · 2 min · jiezi

关于kubernetes:kubernetes-metricsserver

---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: system:aggregated-metrics-reader labels: rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true"rules:- apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: metrics-server:system:auth-delegatorroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegatorsubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: metrics-server-auth-reader namespace: kube-systemroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-readersubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: system:metrics-serverrules:- apiGroups: - "" resources: - pods - nodes - nodes/stats - namespaces verbs: - get - list - watch---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: system:metrics-serverroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-serversubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system ---apiVersion: apiregistration.k8s.io/v1beta1kind: APIServicemetadata: name: v1beta1.metrics.k8s.iospec: service: name: metrics-server namespace: kube-system group: metrics.k8s.io version: v1beta1 insecureSkipTLSVerify: true groupPriorityMinimum: 100 versionPriority: 100---apiVersion: v1kind: ServiceAccountmetadata: name: metrics-server namespace: kube-system---apiVersion: apps/v1kind: Deploymentmetadata: name: metrics-server namespace: kube-system labels: k8s-app: metrics-serverspec: selector: matchLabels: k8s-app: metrics-server template: metadata: name: metrics-server labels: k8s-app: metrics-server spec: serviceAccountName: metrics-server volumes: # mount in tmp so we can safely use from-scratch images and/or read-only containers - name: tmp-dir emptyDir: {} hostNetwork: true containers: - name: metrics-server image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 # command: # - /metrics-server # - --kubelet-insecure-tls # - --kubelet-preferred-address-types=InternalIP args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-insecure-tls=true - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,externalDNS ports: - name: main-port containerPort: 4443 protocol: TCP securityContext: readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 imagePullPolicy: Always volumeMounts: - name: tmp-dir mountPath: /tmp nodeSelector: beta.kubernetes.io/os: linux---apiVersion: v1kind: Servicemetadata: name: metrics-server namespace: kube-system labels: kubernetes.io/name: "Metrics-server" kubernetes.io/cluster-service: "true"spec: selector: k8s-app: metrics-server ports: - port: 443 protocol: TCP targetPort: main-port

July 25, 2020 · 2 min · jiezi

关于kubernetes:kubernetes-metricsserver

---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: system:aggregated-metrics-reader labels: rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true"rules:- apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: metrics-server:system:auth-delegatorroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegatorsubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: metrics-server-auth-reader namespace: kube-systemroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-readersubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: system:metrics-serverrules:- apiGroups: - "" resources: - pods - nodes - nodes/stats - namespaces verbs: - get - list - watch---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: system:metrics-serverroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-serversubjects:- kind: ServiceAccount name: metrics-server namespace: kube-system ---apiVersion: apiregistration.k8s.io/v1beta1kind: APIServicemetadata: name: v1beta1.metrics.k8s.iospec: service: name: metrics-server namespace: kube-system group: metrics.k8s.io version: v1beta1 insecureSkipTLSVerify: true groupPriorityMinimum: 100 versionPriority: 100---apiVersion: v1kind: ServiceAccountmetadata: name: metrics-server namespace: kube-system---apiVersion: apps/v1kind: Deploymentmetadata: name: metrics-server namespace: kube-system labels: k8s-app: metrics-serverspec: selector: matchLabels: k8s-app: metrics-server template: metadata: name: metrics-server labels: k8s-app: metrics-server spec: serviceAccountName: metrics-server volumes: # mount in tmp so we can safely use from-scratch images and/or read-only containers - name: tmp-dir emptyDir: {} hostNetwork: true containers: - name: metrics-server image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 # command: # - /metrics-server # - --kubelet-insecure-tls # - --kubelet-preferred-address-types=InternalIP args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-insecure-tls=true - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,externalDNS ports: - name: main-port containerPort: 4443 protocol: TCP securityContext: readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 imagePullPolicy: Always volumeMounts: - name: tmp-dir mountPath: /tmp nodeSelector: beta.kubernetes.io/os: linux---apiVersion: v1kind: Servicemetadata: name: metrics-server namespace: kube-system labels: kubernetes.io/name: "Metrics-server" kubernetes.io/cluster-service: "true"spec: selector: k8s-app: metrics-server ports: - port: 443 protocol: TCP targetPort: main-port

July 25, 2020 · 2 min · jiezi

关于kubernetes:KubernetesService实践

Service作用和原理 作用:Service的作用次要是用来做负载平衡,dns解析以及对外裸露端口。所有的pod IP和端口都会通过label匹配到,而后通过coredns解析实现了服务发现原理:Service通过iptables或者ipvs对拜访的指标地址进行批改转发数据Service的类型ClusterNodePortLoadBalancerExternalNameCluster类型$ cat myapp-deploy.yaml apiVersion: apps/v1kind: Deploymentmetadata: name: myapp-deployspec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp image: myapp:v1 ports: - containerPort: 80 name: http$ cat myapp-svc.yaml kind: ServiceapiVersion: v1metadata: name: myapp-svcspec: selector: app: myapp ports: - protocol: TCP port: 80 targetPort: 80$ kubectl apply -f myapp-deploy.yamldeployment.apps/myapp-deploy created$ kubectl apply -f myapp-svc.yamlservice/myapp-svc created$ kubectl get deploy,svc,endpointsNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/myapp-deploy 3/3 3 3 28sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d21hservice/myapp-svc ClusterIP 10.105.225.171 <none> 80/TCP 22sNAME ENDPOINTS AGEendpoints/kubernetes 172.16.56.133:8443 5d21hendpoints/myapp-svc 172.17.0.6:80,172.17.0.7:80,172.17.0.8:80 22s$ kubectl run cirros-$RANDOM --rm -ti --image=cirros -- sh/ # curl http://10.105.225.171<h3>Hello World!</h3><b>Hostname:</b> myapp-deploy-ccc8b4bb5-f829g<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>/ ...

July 25, 2020 · 2 min · jiezi

关于kubernetes:KubernetesService实践

Service作用和原理 作用:Service的作用次要是用来做负载平衡,dns解析以及对外裸露端口。所有的pod IP和端口都会通过label匹配到,而后通过coredns解析实现了服务发现原理:Service通过iptables或者ipvs对拜访的指标地址进行批改转发数据Service的类型ClusterNodePortLoadBalancerExternalNameCluster类型$ cat myapp-deploy.yaml apiVersion: apps/v1kind: Deploymentmetadata: name: myapp-deployspec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp image: myapp:v1 ports: - containerPort: 80 name: http$ cat myapp-svc.yaml kind: ServiceapiVersion: v1metadata: name: myapp-svcspec: selector: app: myapp ports: - protocol: TCP port: 80 targetPort: 80$ kubectl apply -f myapp-deploy.yamldeployment.apps/myapp-deploy created$ kubectl apply -f myapp-svc.yamlservice/myapp-svc created$ kubectl get deploy,svc,endpointsNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/myapp-deploy 3/3 3 3 28sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d21hservice/myapp-svc ClusterIP 10.105.225.171 <none> 80/TCP 22sNAME ENDPOINTS AGEendpoints/kubernetes 172.16.56.133:8443 5d21hendpoints/myapp-svc 172.17.0.6:80,172.17.0.7:80,172.17.0.8:80 22s$ kubectl run cirros-$RANDOM --rm -ti --image=cirros -- sh/ # curl http://10.105.225.171<h3>Hello World!</h3><b>Hostname:</b> myapp-deploy-ccc8b4bb5-f829g<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>/ ...

July 25, 2020 · 2 min · jiezi

关于kubernetes:一文了解-Kubernetes

简介: Docker 虽好用,但面对弱小的集群,成千上万的容器,忽然感觉不香了。这时候就须要咱们的配角 Kubernetes 上场了,先来理解一下 Kubernetes 的基本概念,前面再介绍实际,由浅入深步步为营。 镜像下载、域名解析、工夫同步请点击 阿里巴巴开源镜像站Docker 虽好用,但面对弱小的集群,成千上万的容器,忽然感觉不香了。 这时候就须要咱们的配角 Kubernetes 上场了,先来理解一下 Kubernetes 的基本概念,前面再介绍实际,由浅入深步步为营。 对于 Kubernetes 的基本概念咱们将会围绕如下七点开展: 一、Docker 的治理痛点如果想要将 Docker 利用于宏大的业务实现,是存在艰难的编排、治理和调度问题。于是,咱们迫切需要一套管理系统,对 Docker 及容器进行更高级更灵便的治理。 Kubernetes 应运而生!Kubernetes,名词源于希腊语,意为「舵手」或「飞行员」。Google 在 2014 年开源了 Kubernetes 我的项目,建设在 Google 在大规模运行生产工作负载方面领有十几年的教训的根底上,联合了社区中最好的想法和实际。 K8s 是 Kubernetes 的缩写,用 8 代替了 「ubernete」,下文咱们将应用简称。 二、什么是 K8s ?K8s 是一个可移植的、可扩大的开源平台,用于治理容器化的工作负载和服务,可促成申明式配置和自动化。K8s 领有一个宏大且快速增长的生态系统。K8s 的服务、反对和工具宽泛可用。 通过 K8s 咱们能够: 疾速部署利用疾速扩大利用无缝对接新的利用性能节俭资源,优化硬件资源的应用K8s 有如下特点: 可移植:反对私有云,公有云,混合云,多重云 multi-cloud可扩大:模块化,插件化,可挂载,可组合自动化:主动部署,主动重启,主动复制,主动伸缩/扩大三、云架构 & 云原生云和 K8s 是什么关系 云就是应用容器构建的一套服务集群网络,云由很多的大量容器形成。K8s 就是用来治理云中的容器。 常见几类云架构 On-Premises(本地部署)IaaS(基础设施即服务) 用户:租用(购买|调配权限)云主机,用户不须要思考网络,DNS,硬件环境方面的问题。运营商:提供网络,存储,DNS,这样服务就叫做基础设施服务 PaaS(平台即服务) MySQL/ES/MQ/……SaaS(软件即服务) 钉钉财务管理 Serverless 无服务,不须要服务器。站在用户的角度思考问题,用户只须要应用云服务器即可,在云服务器所在的根底环境,软件环境都不须要用户关怀。能够预感:将来服务开发都是 Serverless,企业都构建了本人的公有云环境,或者是应用私有云环境。 云原生 为了让应用程序(我的项目,服务软件)都运行在云上的解决方案,这样的计划叫做云原生。 云原生有如下特点: ...

July 22, 2020 · 3 min · jiezi

关于kubernetes:Kubernetes-10-发布刚六周年IBM-却想招-12-年经验的

IBM 印度分公司最近的一则招聘启事,引发了网友们的热议,起因这则架构师的招聘启事中,明确要求候选人有 12 年以上的 kubernetes 治理教训,截止发稿前,仍旧没有进行解释或批改。 上个月底,IBM 的招聘页面公布了一则云原生架构工程师的招聘,引发了网友们的热议。 这一则招聘启发的,最受争议的其中一条是: 要求候选人需具备 12 年以上 Kubernetes 的治理教训 这一要求被网友疯狂吐槽,认为 Kubernetes 我的项目诞生才不过 6 年,怎么能力有 12 年以上的治理教训? 为 IBM 印度招工,尚未批改措辞该岗位是为 IBM 的印度两个分公司招聘,职位是云原生架构工程师(Cloud Native Infrastructure Engineer),于 6 月 27 日上线。 在职位形容中: 至多 12 年以上 Kubernetes 治理教训;有建设 Kubernetes 平台、部署微服务和其余网络应用、治理平安秘密以及应用 Kubernetes 进行容器编排的实践经验; 对不同节点容器间的通信有肯定理解; 可能在高级网络模式下部署 K8S,有布局、治理、保护 Kubernetes 集群的教训; 对 Kubernetes 集群的日志记录、监控、优化、故障排除有扎实的理解; 对云技术和微服务有丰盛的常识; Kubernetes 的六年之所以被网友们热烈探讨,是因为 Kubernetes 是 Google 在 2014 年启动的。它由 Joe Beda,Brendan Burns 和 Craig McLuckie 创立。Kubernetes v1.0 在 2015 年 7 月 21 日正式公布。 ...

July 22, 2020 · 1 min · jiezi

关于kubernetes:使用Kubernetes两年来的7大经验教训

在Ridecell公司治理基础设施团队几年后,我想在停下来劳动时记录一些想法和经验教训。 1Kubernetes不仅仅是炒作 我在Kubernetes畛域里沉闷了很久,所以这并不出乎我的预料,但当某件事情被大肆宣传的时候,仔细检查一下总是好的。在两年多的工夫里,我的团队实现了从Ansible+Terraform到纯Kubernetes的全面迁徙,在这个过程中,咱们的部署率减少了三倍多,同时将部署谬误缩小到“我都不记得上次是什么时候产生的”的程度。咱们还进步了操作可见性,大量无趣却很重要的自动化工作,以及基础设施中断时的均匀复原工夫。 Kubernetes并不是魔法,但如果被一个懂它的团队应用,那它就是一个十分弱小的工具。 2Traefik + Cert-Manager + Ext-DNS组合很棒 Traefik作为Ingress控制器,Cert-Manager通过LetsEncrypt生成证书,External-DNS治理边缘DNS记录,这三个组合使得HTTP路由和治理像黄油一样顺畅。我始终对Traefik 2.0中删除了很多1.x正文性能的抉择颇有微词,但它们终于在2.2中回归了,只管以不同的模式。作为一个边缘代理,Traefik是一个牢靠的抉择,它具备杰出的指标集成,是所有Ingress控制器中治理部件起码的,以及有一个反馈迅速的开发团队。Cert-Manager配合任意Ingress计划都是一个神奇的工具,如果你在Kubernetes集群中做了TLS,但还没开始应用,那当初就去理解下吧。 External-DNS没有其余两个那么受欢迎,然而对于自动化DNS记录和理论匹配的步骤来说,它的重要性不亚于其余两个。 如果有什么不同的话,这些工具实际上可能使得设置新的HTTPS端点变得太容易。多年来,咱们最终应用了几十个独特的证书,这在Cert Transparency搜寻和LetsEncrypt本人的证书到期正告等方面产生了很多乐音。当前我将会认真思考哪些主机名能够作为全局配置的通配符证书的一部分,以缩小正在应用的证书总数。 3Prometheus很震撼,Thanos并非大材小用 这是我第一次应用Prometheus作为次要的度量零碎,它不愧为该畛域的首要工具。咱们抉择Prometheus-Operator来治理它,这不失为一个好的抉择,让咱们更容易将抓取和规定配置散发到须要它们的利用中。(如果重来的话,)我会在一开始就应用Thanos。我本来认为应用它会过于大材小用,没想到它是那么容易配置,而且在跨区域查问和缩小Prometheus资源应用方面起了很大帮忙,即便咱们没有间接应用主-主互备高可用的设置。 在应用该技术栈时我遇到的最大困扰是Grafana的数据管理,如何存储和组合仪表板。治理仪表板的工具有了微小的增长,例如YAML文件、JSON文件、Kubernetes自定义对象,以及你能想到的其余任何货色。但本源问题还是任何一个工具都很难从头开始编写一个仪表盘,因为Grafana有一百万种不同的配置选项和面板模式等等。咱们最终将它作为一个有状态的零碎来解决,将所有的仪表板进行分组治理,但我并不喜爱这种解决方案。这里是否有一个更好的工作流程呢? 4GitOps才是邪道 如果你应用Kubernetes,那么你应该应用GitOps。对于工具抉择有很多,最简略的就是在你现有的CI零碎中增加运行kubectl apply的作业,始终到应用专用的零碎例如ArgoCD和Flux。不过我动摇地站在ArgoCD营垒,它是一个可作为开始的牢靠的抉择,而且在过来的这些年里它越来越好。就在这周,GitOps-engine的第一个版本曾经上线,其将ArgoCD和Flux放在一个共享的底层零碎上,所以当初更快更好了。如果你不喜爱这些工具的工作流,你当初甚至能够更容易构建新的。在几个月前咱们遇到了一次意外的劫难复原游戏日,因为有人不小心删除了测试集群中的大部分命名空间,多亏了GitOps,咱们的复原形式是在bootstrap库中执行make apply,而后期待零碎自行重建。话说回来,对于一些不能在Git中生存的有状态数据的Velero备份也是很重要的(比方cert-manager的证书,它尽管能够从新签发,但你可能会遇到LetsEncrypt的速率限度)。 咱们遇到最大的问题就是抉择将所有外围基础设施保留在一个存储库中。我仍然认为应用一个繁多的库是正确的设计,但我将会将不同的事物划分到不同的ArgoCD实例中,而不是像当初将所有都放在一个“infra”的实例中。应用单个实例导致更长的收敛工夫和嘈杂的UI,而且如果咱们习惯了正确地宰割咱们的Kustomize定义的话,它就没有多大好处了。 5咱们利用创立更多的Operator 我从一开始就踊跃倒退自定义Operator,且咱们在这方面获得了微小的胜利。咱们从一个自定义资源和控制器开始,用于部署咱们的次要网络应用,并缓缓扩大到该利用和其余利用所需的所有其余自动化。应用一般的Kustomize和ArgoCD进行简略的基础架构服务成果很好,然而当咱们想要管制内部事物时(例如从Kubernetes创立AWS IAM角色,通过kiam来应用),或者当咱们须要某种级别的状态机来管制这些事物时(例如带有SQL迁徙的Django利用部署),咱们都会须要用到Operator。作为其中的一部分,咱们还为咱们所有的自定义对象和控制器建设了一个十分彻底的测试套件,这极大地提高了操作的稳定性和咱们本人对系统正确工作的确定性。 以后有越来越多的形式来构建Opeator,但我依然对kubebuilder相当称心(只管偏心地说,咱们的确随着工夫的推移大幅批改了我的项目构造,所以说它应用的是controller-runtime和controller-tools比kubebuilder自身更偏心)。无论你最喜爱应用哪种语言和框架,都可能有可用的Operator工具包,你相对应该应用它。 6Secret治理仍是难题 Kubernetes有本人的Secret对象,用于在运行时治理机密数据,与容器或与其余对象一起应用,而且这个零碎工作得很好。然而Secret的长期工作流程还是有点乱。把一个原始的Secret提交到Git是很蹩脚的,起因有很多,心愿我不须要列举,那么咱们如何治理这些对象呢?我的解决方案是开发一个自定义的EncryptedSecret类型,它应用AWS KMS对每个值进行加密,同时在Kubernetes中运行的控制器像平常一样将其解密回失常的Secret,还有一个用于解密-编辑-再加密循环的命令行工具。应用 KMS意味着咱们能够通过IAM规定限度KMS密钥的应用来做访问控制,并且只加密值,让文件有正当的差异性。当初有一些基于Mozilla Sops的社区Operator提供了大致相同的工作流,只管Sops在本地编辑工作流程上有点令人丧气。总的来说,这个畛域还须要很多致力,人们应该期待一个可审计、可版本化、可代码审查的工作流,就像在GitOps世界里的所有事件一样。 作为一个相干的问题,Kubernetes的RBAC模型的弱点在Secrets上体现得最为显著。简直在所有状况下,被用于一个事物的Secret必须和应用它的事物在同一个命名空间中,这往往意味着很多不同事物的Secret最终会在同一个命名空间中(数据库明码、厂商API令牌、TLS证书),如果你想给某人(或某事,同样的问题实用于Operator)拜访其中一个,他们就会取得所有的拜访权限。让你的命名空间尽可能的小,任何能够放在它本人的命名空间的货色,都去做吧。你的RBAC策略会感激你当初的做法。 7 原生CI和日志剖析仍是开放性问题 我遇到的两大生态系统坑就是CI和日志剖析。有很多部署在Kubernetes的CI零碎,例如Jenkins、Concourse、Buildkite等。但感觉齐全类原生的解决方案很少。JenkinsX可能是最靠近原生体验的,但它是建设在十分大的复杂性上,我感觉十分惋惜。Prow自身也是十分原生的,但定制化很多,所以也不是一个容易上手的工具。Tekton Pipelines和Argo Workflows都有原生CI零碎的低级管道,然而找到一种办法将其裸露给我的开发团队素来没有超出实践操作人员的范畴。Argo-CI仿佛曾经被放弃了,但Tekton团队仿佛正在踊跃地追踪这个用例,所以我对它的一些改良充满希望。 日志收集基本上是一个已解决的问题,社区集中在Fluent Bit上,将其作为一个DaemonSet发送给一些Fluentd pods,而后再发到你用来存储和剖析的任何零碎上。在存储方面,咱们有ElasticSearch和Loki作为次要的凋谢竞争者,每个都有本人的剖析前端(Kibana和Grafana)。仿佛次要还是最初一部分是我的挫败感的起源。Kibana呈现的工夫更久,剖析性能也很丰盛,但你必须应用商业版来取得根本的操作,比方用户身份验证和用户权限依然十分含糊。Loki要新得多,剖析工具就更少了(子字符串搜寻和每行标签搜寻),至今没有任何针对权限的设计。如果你小心翼翼地确保所有的日志输入是平安的,能够让所有的工程师看到,这没问题,但你要筹备好在SOC/PCI等审计中遇到一些尖利的问题。 8结语 Kubernetes并不是很多人所说的那种可全套交付的解决方案,然而通过一些精心的工程设计和不凡的社区生态系统,它能够成为一个无可比拟的平台。花点工夫学习每个底层组件,你将会在通往容器幸福的路线上走得很好,心愿你在此过程中能防止我的一些谬误。

July 22, 2020 · 1 min · jiezi

关于kubernetes:Pod高级控制器

Pod高级控制器Pod高级控制器 ReplicaSetDeploymentDaemonSetJobCronJobReplicaSet$ cat rs-pod.yaml apiVersion: apps/v1kind: ReplicaSetmetadata: name: rs-examplespec: replicas: 2 selector: matchLabels: app: rs-demo template: metadata: labels: app: rs-demo spec: containers: - name: myapp image: myapp:v1 ports: - name: http containerPort: 80$ kubectl apply -f rs-pod.yaml replicaset.apps/rs-example created$ kubectl get podNAME READY STATUS RESTARTS AGErs-example-4r7rl 1/1 Running 0 4srs-example-hngbv 1/1 Running 0 4s# 批改其中一个pod的标签,replicaset控制器会主动保护正本数量,如果标签不存在的会变成独立pod$ kubectl label pods rs-example-4r7rl app= --overwritepod/rs-example-4r7rl labeled$ kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELSrs-example-4r7rl 1/1 Running 0 37s app=rs-example-54589 1/1 Running 0 9s app=rs-demors-example-hngbv 1/1 Running 0 37s app=rs-demo ...

July 21, 2020 · 3 min · jiezi

关于kubernetes:Chaos-Mesh®-正式进入-CNCF-沙箱托管项目

近日,云原生计算基金会 (CNCF) 发表云原生的混沌工程 Chaos Mesh 正式进入 CNCF 沙箱托管我的项目,这是 CNCF 接收的第二个由 PingCAP 团队设计并研发的我的项目。 Chaos Mesh 是一个云原生的混沌工程(Chaos Engineering)平台,可在 Kubernetes 环境中进行混沌测试,在各种简单的环境下可应用混沌工程来保证系统能失常稳固运行。现阶段,组成部分包含: Chaos Operator:混沌编排的外围组件 —— 齐全开源;Chaos Dashboard:用于治理、设计、监控混沌试验的 Web UI —— 开发中。相比其余混沌平台,Chaos Mesh 具备以下劣势: 专一于 Kubernetes 平台。Chaos Mesh 致力于打造齐全云原生的混沌测试平台,只有你零碎能够跑在 Kubernetes 下面,那么就能够无缝的集成 Chaos Mesh。可拓展性。基于目前 Chaos Mesh 灵便的设计,一方面易于拓展新的故障注入类型,另一方面能够十分不便的集成到其余的测试框架中。丰盛的故障注入伎俩。Chaos Mesh 能全方位的帮你对网络,磁盘,文件系统,操作系统等进行故障注入。咱们前面也会提供对 Kubernetes,或者云服务本身进行 chaos 的能力。易于应用。你无需关注 Chaos Mesh 的底层实现细节,只需用 YAML 配置好混沌试验,就能够施行,前面所有的试验是全自动化的。咱们也提供了 Dashboard 能让你在网页上就轻松的进行试验。可观测性。Chaos Mesh 的 Dashboard 能很方便管理和监控混沌试验。此外 Chaos Mesh 还提供了 Grafana 插件,应用此插件能够十分不便的将混沌试验的和利用的监控联合起来,间接从利用的监控界面差看到什么时候进行了什么试验以及本人的零碎以后的运行状况。弱小的开源社区反对。Chaos Mesh 的社区成长的十分迅速,咱们非常高兴的看到大部分的性能曾经由社区反对,包含来自小鹏汽车的开发者和咱们合作开发独特保护此我的项目。截止目前,包含小鹏汽车、Dailymotion、网易伏羲实验室、JuiceFS、美团等在内的企业都正在应用 Chaos Mesh,来极大晋升对系统的信念。 PingCAP 长期沉闷于 CNCF ,在 CNCF 公布的 2019 年度报告中,PingCAP 在 2019 年对 CNCF 的奉献数为 55837,全球排名第六,国内排名第一。此前,由 PingCAP 团队设计并开发的开源分布式事务 Key-Value 数据库 TiKV 于 2018 年 8 月被 CNCF 发表接收为沙箱云原生我的项目,并在 2019 年 5 月从 沙箱升级至孵化我的项目,目前正在毕业流程中。在退出 CNCF 近 2 年的工夫里,得益于基金会和社区贡献者们的反对,TiKV 获得了里程碑式的倒退,置信 Chaos Mesh 退出 CNCF 后可能失去更快的成长,最终达到“成为云原生分布式测试规范平台”的指标。 ...

July 21, 2020 · 1 min · jiezi

关于kubernetes:Kubernetes-Egress-网络策略指南

作者:Viswajith Venugopal翻译:Bach(才云) 校对:bot(才云)、星空下的文仔(才云) Kubernetes 中的网络策略用于指定 Pod 组之间以及其与内部网络端点之间的通信,它就像是 Kubernetes 的防火墙。与大多数 Kubernetes 对象一样,网络策略非常灵活,性能也很弱小。如果理解应用程序中服务的确切通信模式,咱们就能够通过网络策略将通信限度在咱们想要范畴之内。 Ingress 与 Egress 网络策略可用于指定 Pod 的入口(Ingress)流量和进口(Egress)流量,其规定如下: 如果容许集群内部网络端点到 Pod 的通信,那么该端点能够拜访 Pod。如果容许 Pod 到集群内部网络端点的通信,那么 Pod 也能够拜访该端点。如果 Pod(A)到 Pod(B)的流量被容许,那么流量能够通过 A 的进口以及 B 的入口。留神这是单向的,流量从 B 到 A,那么只能从 B 的进口到 A 的入口。设置 Ingress 在实现入口网络策略的设置并胜利运行后,咱们再设置进口网络策略。这样做的起因有两个:首先,一次执行两项操作比拟艰难,而且咱们很难晓得是因为入口还是进口配置导致的网络连接失败;其次,进口网络策略通常更难以施行。限度进口可能会引发各种谬误,从而影响利用程序运行。 尽管确定网络端点到 Pod 的通信非常简单,但要确定 Pod 到网络端点的连贯形式会比较复杂。之所以呈现这一问题,这是因为: 作为惯例性能的一部分,Deployment 通常会查问一堆内部服务,依据它们在拜访这些服务时解决超时的形式,性能可能会受到一些轻微而又难以察看的影响。Deployment 须要可能与 DNS 服务器通信,以便和其余任何服务器通信,除非这些服务器间接通过 IP 与服务分割。对 Pod Egress 进行隔离 每个网络策略都有一个 podSelector 字段,该字段会抉择一组(0 个或多个)Pod。当网络策略抉择了一个 Pod 时,就称该网络策略实用于该 Pod。 此外,每个网络策略都能够依据 policyTypes 字段的值利用于入口和进口。如果 YAML 中未指定此字段,它的值会基于策略中的入口、进口规定默认设置,但默认设置并不靠谱,咱们最好进行明确的设置。 ...

July 21, 2020 · 2 min · jiezi

关于kubernetes:使用Thanos实现Prometheus指标联邦

本文来自Rancher Labs Prometheus是CNCF中曾经毕业的我的项目之一,次要用于监控和告警。在Kubernetes生态中,它是利用最为宽泛的监控和告警工具之一。Rancher用户能够通过应用内置的监控堆栈来疾速利用Prometheus。 Prometheus将其指标(metrics)作为时序数据库存储在本地磁盘上,因而Prometheus的本地存储会受到磁盘大小以及所能保留的指标数量的制约。然而,Prometheus容许与近程系统集成,通过_remotewrite和_remoteread指令读写指标,同时它还反对大量近程端点和存储集成。 联邦能够实现可扩大的Prometheus监控设置,或者将相干的指标从一个服务的Prometheus拉取到另一个Prometheus中。 在本文中,咱们将摸索一个疾速和简略的形式来设置Rancher监控近程端点与Thanos receive的集成。Thanos是一个开源的、高可用的Prometheus设置,有长期指标存储性能。你能够应用这个解决方案在所有的Prometheus实例中实现联邦指标,并容许地方Grafana dashboard在Thanos上运行。 重要揭示:作为指标联邦的一部分,我的项目/集群指标将不在Rancher治理立体内。此外,集群管理员必须确保建设适当的访问控制机制,以限度对该指标存储的拜访。装置Thanos在本篇文章中,咱们能够应用kube-thanos在Kubernetes集群上疾速设置Thanos。 咱们将须要以下Thanos组件: Thanos存储gatewayThanos接收器(receiver)Thanos查询器(querier)对象存储该解决方案如下所示: +Tenant's Premise | Provider Premise | | +------------------------+ | | | | +-------->+ Object Storage | | | | | | | +-----------+------------+ | | ^ | | S3 API | S3 API | | | | | +-----------+------------+ | | | | Store API | | | Thanos Store Gateway +<-----------------------+ | | | | | | | +------------------------+ | | | | | +---------------------+ | | | |+--------------+ | +-----------+------------+ +---------+--------+| | | Remote | | Store API | || Prometheus +------------->+ Thanos Receiver +<-------------+ Thanos Querier || | | Write | | | |+--------------+ | +------------------------+ +---------+--------+ | ^ | |+--------------+ | || | | PromQL || User +----------------------------------------------------------------+| | |+--------------+ | +起源:Thanos receive proposal ...

July 20, 2020 · 1 min · jiezi

关于kubernetes:Pod生命周期

Pod生命周期1. Pod生命周期过程中的状态(或者叫相位) [x] Pending: API Server创立了pod资源对象并存入etcd,但未被调度实现或仍处于下载镜像过程[x] Running: pod已被调度至节点,并且所有容器都被kubelet创立实现[x] Succeeded: pod中的所有容器都曾经胜利终止并且不会被重启[x] Failed: 所有容器曾经被终止,但至多有一个容器终止失败,即容器返回非0值的退出状态或被已被零碎终止[x] Unknown: API Server无奈失常获取到pod对象状态信息,通常是因为其无奈与所在工作节点的kubelet通信所致2.Pod创立过程 3.针对pod生命周期,做一些事先,事中,预先的一些操作初始化容器生命周期钩子函数容器探测3.1 初始化容器 $ cat initC-pod.yamlapiVersion: v1kind: Podmetadata: name: myapp-pod labels: app: myappspec: containers: - name: myapp-container image: busybox:1.28 command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"] - name: init-mydb image: busybox:1.28 command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]$ cat initC-service.yamlkind: ServiceapiVersion: v1metadata: name: myservicespec: ports: - protocol: TCP port: 80 targetPort: 9367---kind: ServiceapiVersion: v1metadata: name: mydbspec: ports: - protocol: TCP port: 80 targetPort: 9377创立pod,不创立service,pod在初始化时查看域名失败,容器会停留在init状态$ kubectl apply -f initC-pod.yaml $ kubectl get podNAME READY STATUS RESTARTS AGEmyapp-pod 0/1 Init:0/2 0 7s$ kubectl describe -f initC-pod.yaml... init-myservice: Container ID: docker://c22ec8d0b0ab5cb9a55274892ae7f818198394f9fb851cf672b60dc30099df1f Image: busybox Image ID: docker-pullable://busybox@sha256:9ddee63a712cea977267342e8750ecbc60d3aab25f04ceacfa795e6fce341793 Port: <none> Host Port: <none> Command: sh -c until nslookup myservice; do echo waiting for myservice; sleep 2; done; State: Running Started: Sun, 19 Jul 2020 13:54:43 +0800 Ready: False Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-58nkl (ro) init-mydb: Container ID: Image: busybox Image ID: Port: <none> Host Port: <none> Command: sh -c until nslookup mydb; do echo waiting for mydb; sleep 2; done; State: Waiting Reason: PodInitializing Ready: False Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-58nkl (ro)...$ kubectl logs myapp-pod -c init-myservicnslookup: can't resolve 'myservice.default.svc.cluster.local'Server: 10.96.0.10Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local$ kubectl logs myapp-pod -c init-mydbError from server (BadRequest): container "init-mydb" in pod "myapp-pod" is waiting to start: PodInitializing ...

July 19, 2020 · 2 min · jiezi

关于kubernetes:minikube安装方法

minikube装置办法环境查看sysctl -a | grep -E --color 'machdep.cpu.features|VMX'呈现VMX阐明反对 在装置minikube之前先在本人的机器下面装置虚拟机docker (driver installation)virtualbox (driver installation)podman (driver installation) (EXPERIMENTAL)vmwarefusionkvm2 (driver installation)hyperkit (driver installation)hyperv (driver installation) Note that the IP below is dynamic and can change. It can be retrieved with minikube ip.vmware (driver installation) (VMware unified driver)parallels (driver installation)none (Runs the Kubernetes components on the host and not in a virtual machine. You need to be running Linux and to have Docker installed.通过brew装置装minikubebrew install minikube通过minikube二进制包形式装置curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 \ && chmod +x minikubesudo mv minikube /usr/local/bin# vm-driver (hyperkit, vmware, virtualbox)# vmwarefusion被启用,如果应用vmware驱动失败,须要装置驱动brew install docker-machine-driver-vmwareminikube start --vm-driver=vmware --memory 8192 --cpus 4 ...

July 19, 2020 · 1 min · jiezi

关于kubernetes:flink-on-native-kubernetes

上一章讲了flink 的 application mode。明天咱们次要通过该模式提交WordCount作业,并且抉择的是native kubernetes。 Native Kubernetes 原理下图形容了flink如何与kubernetes集成: 创立Flink Kubernetes Session集群时,Flink客户端将首先连贯到Kubernetes ApiServer提交集群形容,包含ConfigMap标准,Job Manager服务标准,Job Manager Deployment标准和Owner Reference。而后,Kubernetes将创立JobManager Deployment,在此期间,Kubelet将拉取镜像,筹备并装置卷,而后执行启动命令。启动JobManager Pod 后,Dispatcher和KubernetesResourceManager 就绪可用,并且集群已筹备好承受一个或多个作业。 当用户通过Flink客户端提交作业时,客户端将生成Job Graph,并将其与用户jar一起上传到Dispatcher。 JobManager向KubernetesResourceManager申请插槽的资源。如果没有可用的插槽,资源管理器将创立TaskManager Pod并在集群中注册它们。 示例Application mode容许用户创立一个蕴含其Job和Flink运行时的镜像,这将依据须要主动创立和销毁集群组件。 Flink社区提供了针对任何用例定制的根本docker镜像。 下载 首先去官网下载 flink1.11。包中蕴含以下内容: bin conf Dockerfile examples lib LICENSE licenses log NOTICE opt plugins README.txt其中: bin 下蕴含了flink相干的一些可执行文件以及一些shell脚本,次要用来提交工作或是创立进行集群conf 蕴含了flink和日志等相干的配置文件examples, 顾名思义,就是一些demo示例,比方咱们明天的WordCount 就位于此门路下lib 蕴含 flink 依赖的包opt 蕴含了一些扩大的包,比方flink 对接s3的专用包plugins 蕴含了监控相干,比方对接prometheus,graphite等。构建镜像 而后咱们创立一个Dockerfile,用于定制镜像。Dockerfile内容如下: FROM flinkRUN mkdir -p $FLINK_HOME/usrlibCOPY ./examples/streaming/WordCount.jar $FLINK_HOME/usrlib/my-flink-job.jar构建镜像: docker build -t iyacontrol/flink-world-count:v0.0.1 .Sending build context to Docker daemon 362.7MBStep 1/3 : FROM flinklatest: Pulling from library/flinke9afc4f90ab0: Already exists 989e6b19a265: Already exists af14b6c2f878: Already exists 68a79816c3e1: Pull complete 037cc5cb1b83: Pull complete d3efdb331614: Pull complete bf82d2b871ad: Pull complete 4ff2e8c5d83f: Pull complete f15a0d59303a: Pull complete 81130e2e9fdd: Pull complete 40bdeebc27c6: Pull complete 8fe3a85e5402: Pull complete Digest: sha256:665db47d0a2bcc297e9eb4df7640d3e4c1d398d25849252a726c8ada112722cfStatus: Downloaded newer image for flink:latest ---> 43f070a908e6Step 2/3 : RUN mkdir -p $FLINK_HOME/usrlib ---> Running in c44a726b85a9Removing intermediate container c44a726b85a9 ---> 67ab6686e049Step 3/3 : COPY ./examples/streaming/WordCount.jar $FLINK_HOME/usrlib/my-flink-job.jar ---> ab3686ebc7e5Successfully built ab3686ebc7e5推送镜像到镜像仓库: ...

July 17, 2020 · 2 min · jiezi

关于kubernetes:Kubernetes-微内核的分布式操作系统

现在,Kubernetes 曾经成为分布式集群管理系统和私有云/公有云的事实标准。实际上,Kubernetes 是一个分布式操作系统,它是 Google 在分布式操作系统畛域十余年工程教训和智慧的结晶,而 Google 始终以来都治理着世界上最大的分布式集群,在分布式操作系统畛域的钻研和意识当先于全世界。因而,2014年公布的 Kubernetes 能在短短几年工夫内就超过了诸多前辈,大获胜利。 作为分布式操作系统,Kubernetes(包含其前代产品 Google Borg)的呈现远远晚于 UNIX、Linux、Windows 等驰名的单机操作系统,Kubernetes 架构设计天然地继承了很多单机操作系统的宝贵遗产,微内核架构就是这些遗产中最重要的一份。在本文接下来的局部,咱们将专一于微内核(microkernel)这个概念及其对 Kubernetes 架构的影响。 什么是微内核?在介绍微内核的时候,咱们有必要同时回顾一下单机操作系统的历史,以了解其价值所在。本章中以「操作系统」指代「单机操作系统」。 UNIX 的衰亡电子计算机诞生之后,在上个世纪70年代以前,呈现过许许多多的操作系统,DOS、OS/360、Multics 是其中的出名代表,这是操作系统畛域的开荒时代。20年来的开荒孕育出了平凡的成绩:随着 CPU 技术的倒退,UNIX 于1969年诞生了,这是一个真正意义上的分时操作系统。 图片起源:维基百科 借助新的 CPU 技术的反对,UNIX 将软件系统划分为内核(kernel)和用户态程序(userland programs)两局部。内核是一组中断处理程序的汇合,把硬件的能力封装为操作系统性能调用(system calls),用户态程序通过零碎调用应用硬件性能,用户态程序运行于各自的过程中,所有用户态过程都共享同一个内核,每当零碎调用或中断产生,UNIX 便陷入(trap)内核,内核执行零碎调用,与此同时,内核中的分时调度算法将决定把 CPU 交给哪个过程,并治理过程的上下文切换。另外,UNIX 把(简直)所有硬件都封装为文件。UNIX 还提供了一个非凡的用户态程序 shell,供用户间接应用零碎,通过内核提供的过程间通信能力,shell让 用户能够把一系列应用程序组合起来,解决简单的需要,作者称这个设计思维为「KISS」(Keep It Simple and Stupld)。UNIX 的所有设计思维在过后是都是十分了不起的创举。 UNIX 岂但本身对业界产生了微小的间接奉献,还成为所有古代操作系统的底本,两位作者 Ken Tompson 和 Dennis Ritchie 因而荣获1983年度的图灵奖。 UNIX 诞生于贝尔实验室,该实验室属于美国国家电信电报公司(AT&T),见识到 UNIX 的弱小威力之后,AT&T 做出了一个看似自私的决定:将 UNIX 开源(初期只对大学开源),这使得所有古代操作系统得以诞生。尽管 AT&T 最终被分拆,辉煌不再,但这个决定对人们的奉献绵延至今。在21世纪20年代的明天,无论是 MacOS、Windows、Linux,都间接受到 UNIX 的影响,而 iOS 来自 MacOS,Android 来自 Linux,因而 UNIX 的灵魂依然活在每个人的手机中、活在每个手机 App 后盾的服务中。 ...

July 17, 2020 · 3 min · jiezi

生产环境运行gRPC服务的挑战

为什么要应用gRPC?在云原生的背景下,微服务大行其道。拆分的服务越来越细粒度,绝对于之前的单体架构设计,服务之间通信的品质成为影响整体服务质量的一个重要环节。 此外当初的研发体系,很少只存在一种语言,往往是多语言。此时,解决多语言交互也是一个必须解决的问题。 gRPC (gRPC Remote Procedure Calls) 是Google发动的一个开源近程过程调用 (Remote procedure call) 零碎。该零碎基于 HTTP/2 协定传输,应用Protocol Buffers 作为接口描述语言。 其余性能: 认证( authentication)双向流(bidirectional streaming)流控制(flow control)超时(timeouts)最常见的利用场景是: 微服务框架下,多种语言服务之间的高效交互。将手机服务、浏览器连贯至后盾产生高效的客户端库然而运行gRPC服务也带给咱们一些挑战,大多数是因为HTTP/2 复用链接。 gRPC带来的挑战gRPC只是一个RPC通信框架,并不是一个服务治理框架。尤其在云原生的环境下,比方kubernetes中,因为资源缓和被驱赶,或是弹性伸缩等起因,客户端如何能及时感知到新增的server,以及剔除掉销毁的资源实例是一个挑战。因为HTTP/2 复用链接,如何解决负载平衡的问题也是另外一个挑战。 gRPC的负载平衡能够分为客户端负载平衡和代理负载平衡。 上面咱们讲下咱们理论应用过程中一些计划。 解决方案 1: 基于envoy的ingress controller该计划又可称为边缘ingress。因为数据层envoy通过daemonset的形式部署到集群中,这样相当于每个node节点上部署了一个代理。边缘部署的形式,满足了高可用的要求。 如果A服务须要拜访B服务,那么创立B服务的ingress,拜访域名为http://b.service.com。 这种计划相当于代理的形式解决负载平衡。服务注册和发现利用了k8s原生的服务发现能力。 该计划的毛病是,一个envoy要解决node节点上所有的流量,可能会因为某个服务的流量问题,影响了其余的服务。 解决方案 2: gRPC client拜访方须要集成对应语言的gRPC client。 利用了client 的客户端负载平衡的能力。不过这种计划,须要可能获取到B服务可用的server列表。 如何实现服务注册和发现那? 咱们能够为B服务,创立一个Headless service,而后拜访b.default.cluster.local ,coredns 会返回可用的Pod列表。 此时,将b.default.cluster.local 配置到gRPC client,客户端主动会通过dns,返回可用列表,用于客户端负载平衡。 该计划毛病是客户端引入了sdk,减少服务的复杂性。 解决方案 3: 将envoy 以 Sidecar 的模式部署将envoy以Sidercar的模式部署,联合了前两种计划的劣势,客户端代码不必引入非业务逻辑的代码,每个sidecar 只解决本client的流量逻辑。 论断除了负载平衡和服务发现,咱们还须要实现优雅退出,因为不论是dns服务发现,还是k8s原生服务发现,均有肯定的提早。 此时咱们能够简略利用Pod生命周期的pre-stop钩子。 解决方案1和解决方案3,除了解决了负载平衡的问题,还能通过envoy 裸露进去的metrics和access log,减少了服务的可察看性。 ...

July 17, 2020 · 1 min · jiezi

探究-flink111-Application-模式

随着流式计算的衰亡,实时剖析成为古代商业的利器。越来越多的平台和公司基于Apache Flink 构建他们的实时计算平台,并saas化。 这些平台旨在通过简化利用的提交来升高最终用户的应用累赘。通常的做法是,会提供一个诸如治理平台的web程序,不便使用者提交利用,并且该平台集成了一些权限,监控等内容。这个治理平台我能够叫作部署服务。 然而当初这些平台遇到一个大问题是部署服务是一个耗费资源比拟大的服务,并且很难计算出理论资源限度。比方,如果咱们取负载的平均值,则可能导致部署服务的资源实在所需的值远远大于限度值,最坏的状况是在肯定工夫影响所有的线上利用。然而如果咱们将取负载的最大值,又会造成很多不必要的节约。基于此,Flink 1.11 引入了另外一种部署选项 Application Mode, 该模式容许更加轻量级,可扩大的利用提交过程,将之前客户端的利用部署能力平均扩散到集群的每个节点上。 为了了解这个问题以及Application Mode 是如何解决这个问题,咱们将在下文介绍以后flink中利用执行的模式。 Flink 中的利用执行Flink中利用的执行会波及到三局部:_Client,JobManager 和 TaskManagers。_Client 负责提交利用到集群,JobManager 负责利用执行期间一些必要的记录工作,TaskManager 负责具体的利用执行。具体的架构图如下: 以后部署模式在引入Application Mode(Flink1.11) 之前,Flink 反对 Session 和 Per-Job 两种mode,这两种有不同的集群生命周期和资源隔离。 Session 模式Session 模式假设曾经存在一个集群,并任何的提交的利用都在该集群里执行。因而会导致资源的竞争。该模式的劣势是你无需为每一个提交的工作破费精力去合成集群。然而,如果Job异样或是TaskManager 宕掉,那么该TaskManager运行的其余Job都会失败。除了影响到工作,也意味着潜在须要更多的复原操作,重启所有的Job,会并发拜访文件系统,会导致该文件系统对其余服务不可用。此外,单集群运行多个Job,意味着JobManager更大的负载。这种模式适宜启动提早十分重要的短期作业。 Per-Job 模式在Per-Job模式下,集群管理器框架(例如YARN或Kubernetes)用于为每个提交的Job启动一个 Flink 集群。Job实现后,集群将敞开,所有残留的资源(例如文件)也将被革除。此模式能够更好地隔离资源,因为行为异样的Job不会影响任何其余Job。另外,因为每个应用程序都有其本人的JobManager,因而它将记录的负载扩散到多个实体中。思考到后面提到的Session模式的资源隔离问题,Per-Job模式适宜长期运行的Job,这些Job能够承受启动提早的减少以反对弹性。 总而言之,在Session 模式下,集群生命周期独立于集群上运行的任何Job,并且集群上运行的所有Job共享其资源。Per-Job模式抉择为每个提交的Job承当拆分集群的费用,以提供更好的资源隔离保障,因为资源不会在Job之间共享。在这种状况下,集群的生命周期将与job的生命周期绑定在一起。 利用提交Flink 利用的执行蕴含两个阶段: pre-flight: 在main()办法调用之后开始。runtime: 一旦用户代码调用 execute() 就会触发该阶段。main()办法应用Flink的API(DataStream API,Table API,DataSet API)之一结构用户程序。当main()办法调用env.execute()时,用户定义的pipeline将转换为Flink运行时能够了解的模式,称为job graph,并将其传送到集群中。 只管有一些不同,然而 对于 Session 模式 和 Per-Job模式 , pre-flight 阶段都是在客户端实现的。 对于那些在本人本地计算机上提交工作的场景(本地计算机蕴含了所有运行Job所需的依赖),这通常不是问题。然而,对于通过诸如部署服务之类的近程进行提交的场景,此过程包含: 下载利用所需的依赖执行main()办法提取 job graph将依赖和 job graph 传输到集群有可能须要期待后果这样客户端大量耗费资源,因为它可能须要大量的网络带宽来下载依赖项并将二进制文件运送到集群,并且须要CPU周期来执行main()办法。随着更多用户共享同一客户端,此问题会更加显著。 ...

July 17, 2020 · 1 min · jiezi

Kubernetes-中的垃圾回收

构想这么一个场景:咱们在 K8s 上创立了一个对象,它依据须要生成正本集和 Pod。在查看时,咱们脱漏了容器某个属性的设置,因而又从新编辑了 Deployment。新的 Deployment 就产生了新的正本集对象和新的 Pod。这里就呈现了一个问题,旧的正本集和 Pop 去哪了?另外,如果间接删除 Deployment,那正本集和 Pod 又会如何?事实就是,在删除 Deployment 后,正本集和 Pod 也会一起被删除,要不然集群早就乱套了。 在这个场景之下,咱们能够深刻思考几个问题:在 K8s 中该如何实现级联删除?有几种级联删除策略?在 K8s 中有没有可能存在孤儿对象(orphan object)?这些问题其实就是典型的垃圾回收(garbage collection,GC)问题。本文将介绍 K8s 中垃圾回收的概念以及实现办法。 什么是垃圾回收? 一般来说,垃圾回收(GC)就是从零碎中删除未应用的对象,并开释调配给它们的计算资源。GC 存在于所有的高级编程语言中,较低级的编程语言通过零碎库实现 GC。 GC 最常见的算法之一是 mark-and-sweep,这个算法会标记将删除的对象,再进行删除,如下图所示: OwnerRefernce 在面向对象的语言中,一些对象会援用其余对象或者间接由其余对象组成,k8s 也有相似模式,例如正本集治理一组 Pod,而 Deployment 又治理着正本集。 但与面向对象语言不同的是,在 K8s 对象的定义中,没有明确所有者之间的关系,那么零碎要如何确定它们的关系呢?其实,在 K8s 中,每个隶属对象都具备 惟一数据字段名称 metadata.ownerReferences 用于确定关系。 从 Kubernetes v1.8 开始,K8s 对于 ReplicaSet、StatefulSet、DaemonSet、Deployment、Job、 CronJob 等创立或治理的对象,会主动为其设置 ownerReferences 的值。如果有须要,咱们还能够手动设置 ownerReferences。 以下内容显示了 core-dns Deployment 上 metadata.ownerReferences 的值。 k get deployment -n kube-system -o wideNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGEScoredns 2/2 2 2 44d coredns k8s.gcr.io/coredns:1.6.7k get rs -n kube-system -o json | jq ".items[0].metadata.name, .items[0].metadata.ownerReferences""coredns-66bff467f8"[ { "apiVersion": "apps/v1", "blockOwnerDeletion": true, "controller": true, "kind": "Deployment", "name": "coredns", "uid": "d8f29b78-439c-497e-9a45-7c33bd626a9f" }]k get pods coredns-66bff467f8-rsnmg -n kube-system -o json | jq ".metadata.name, .metadata.ownerReferences""coredns-66bff467f8-rsnmg"[ { "apiVersion": "apps/v1", "blockOwnerDeletion": true, "controller": true, "kind": "ReplicaSet", "name": "coredns-66bff467f8", "uid": "085d5398-1358-43e2-918e-2e03da18c7bd" }]认真察看上述命令的输入,其实它和其余对象 GC 之间是有些许差异的。对象关联参考金字塔是颠倒的: ...

July 16, 2020 · 2 min · jiezi

误删节点或集群怎么办这里有一颗后悔药

本文来自Rancher Labs 作者介绍王海龙,Rancher中国社区技术经理,负责Rancher中国技术社区的保护和经营。领有6年的云计算畛域教训,经验了OpenStack到Kubernetes的技术改革,无论底层操作系统Linux,还是虚拟化KVM或是Docker容器技术都有丰盛的运维和实践经验。 在理论应用Rancher过程中,偶然会因为误操作删除了System Workload、节点或集群, 导致集群状态异样而无法访问。如果用户不理解复原办法,通常会从新增加节或从新搭建集群。 本文将依据以下几个场景来介绍如何复原因为误操作引起的Rancher集群故障: 如何复原System Project Workload如何复原从Rancher UI或kubectl误删的节点如何复原执行过清理节点脚本的节点如何复原被删除的custom集群重要阐明本文档基于Rancher 2.4.x测试,其余版本操作可能会略有不同本文介绍的场景均是针对custom集群如果您在此过程中遇到问题,则应该相熟Rancher架构/故障排除您应该相熟单节点装置和高可用装置之间的体系结构差别如何复原System Project WorkloadSystem Project中蕴含了一些保障该集群可能失常运行的一些workload,如果删除某些workload可能会对该集性能群造成影响。 通常状况下,通过RKE创立的custom集群应包含以下workload: 上面咱们来别离介绍如果误删了这些workload之后应如何复原。 复原cattle-cluster-agent和cattle-node-agent模仿故障 从System Project下删除 cattle-cluster-agent和cattle-node-agent 生成Kubeconfig和集群yaml 1.在Rancher UI上创立API token(用户-> API & Keys)并保留Bearer Token 2.抉择集群后,在Rancher UI(格局为c-xxxxx)中找到其clusterid,并在地址栏中找到它。 3.依据步骤1-2获取的变量替换:RANCHERURL、CLUSTERID、TOKEN(主机须要装置curl和jq) # Rancher URLRANCHERURL="https://192.168.99.201"# Cluster IDCLUSTERID="c-v6mtr"# TokenTOKEN="token-klt5n:2smg6n5cb5vstn7qm797l9fbc7s9gljxjw528r7c5c4mwf2g7kr6nm"# Valid certificatescurl -s -H "Authorization: Bearer ${TOKEN}" "${RANCHERURL}/v3/clusterregistrationtokens?clusterId=${CLUSTERID}" | jq -r '.data[] | select(.name != "system") | .command'# Self signed certificatescurl -s -k -H "Authorization: Bearer ${TOKEN}" "${RANCHERURL}/v3/clusterregistrationtokens?clusterId=${CLUSTERID}" | jq -r '.data[] | select(.name != "system") | .insecureCommand'以上命令执行胜利后,将返回导入集群的命令,请做好备份,命令如下: ...

July 15, 2020 · 2 min · jiezi

万级K8s集群背后-etcd-稳定性及性能优化实践

1背景与挑战 随着腾讯自研上云及私有云用户的迅速增长,一方面,腾讯云容器服务TKE服务数量和核数大幅增长, 另一方面咱们提供的容器服务类型(TKE托管及独立集群、EKS弹性集群、edge边缘计算集群、mesh服务网格、serverless knative)也越来越丰盛。各类容器服务类型背地的外围都是K8s,K8s外围的存储etcd又对立由咱们基于K8s构建的etcd平台进行治理。基于它咱们目前治理了千级etcd集群,背地撑持了万级K8s集群。 在万级K8s集群规模下的咱们如何高效保障etcd集群的稳定性? etcd集群的稳定性危险又来自哪里? 咱们通过基于业务场景、历史遗留问题、现网经营教训等进行稳定性危险模型剖析,危险次要来自旧TKE etcd架构设计不合理、etcd稳定性、etcd性能局部场景无奈满足业务、测试用例笼罩有余、变更治理不谨严、监控是否全面笼罩、隐患点是否能主动巡检发现、极其劫难故障数据安全是否能保障。 后面所形容的etcd平台曾经从架构设计上、变更治理上、监控及巡检、数据迁徙、备份几个方面水平解决了咱们治理的各类容器服务的etcd可扩展性、可运维性、可观测性以及数据安全性,因而本文将重点形容咱们在万级K8s场景下面临的etcd内核稳定性及性能挑战,比方: •数据不统一 •内存泄露 •死锁 •过程Crash •大包申请导致etcd OOM及丢包 •较大数据量场景下启动慢 •鉴权及查问key数量、查问指定数量记录接口性能较差 本文将繁难形容咱们是如何发现、剖析、复现、解决以上问题及挑战,以及从以上过程中咱们取得了哪些教训及教训,并将之利用到咱们的各类容器服务存储稳定性保障中。 同时,咱们将解决方案全副奉献、回馈给etcd开源社区, 截止目前咱们奉献的30+ pr已全副合并到社区。腾讯云TKE etcd团队是etcd社区2020年上半年最沉闷的奉献团队之一, 为etcd的倒退奉献咱们的一点力量, 在这过程中特别感谢社区AWS、Google、Ali等maintainer的反对与帮忙。 2稳定性优化案例分析 从GitLab误删主库失落局部数据到GitHub数据不统一导致中断24小时,再到号称"不沉航母"的AWS S3故障数小时等,无一例外都是存储服务。稳定性对于一个存储服务、乃至一个公司的口碑而言至关重要,它决定着一个产品生与死。稳定性优化案例咱们将从数据不统一的严重性、两个etcd数据不统一的bug、lease内存泄露、mvcc 死锁、wal crash方面论述,咱们是如何发现、剖析、复现、解决以上case,并分享咱们从每个case中的取得的播种和反思,从中吸取教训,防患于未然。 数据不统一(Data Inconsistency) 谈到数据不统一导致的大故障,就不得不具体提下GitHub在18年一次因网络设备的例行保护工作导致的美国东海岸网络核心与东海岸次要数据中心之间的连贯断开。尽管网络的连通性在43秒内得以复原,然而短暂的中断引发了一系列事件,最终导致GitHub 24小时11分钟的服务降级,局部性能不可用。 GitHub应用了大量的MySQL集群存储GitHub的meta data,如issue、pr、page等等,同时做了货色海岸跨城级别的容灾。故障外围起因是网络异样时GitHub的MySQL仲裁服务Orchestrator进行了故障转移,将写入数据定向到美国西海岸的MySQL集群(故障前primary在东海岸),然而美国东海岸的MySQL蕴含一小段写入,尚未复制到美国西海岸集群,同时故障转移后因为两个数据中心的集群当初都蕴含另一个数据中心中不存在的写入,因而又无奈平安地将主数据库故障转移回美国东海岸。 最终, 为了保障保障用户数据不失落,GitHub不得不以24小时的服务降级为代价来修复数据一致性。 数据不统一的故障严重性显而易见,然而etcd是基于raft协定实现的分布式高牢靠存储系统,咱们也并未做跨城容灾,按理数据不统一这种看起来高大上bug咱们是很难遇到的。然而幻想是美妙的,事实是残暴的,咱们不仅遇到了不堪设想的数据不统一bug, 还一踩就是两个,一个是重启etcd有较低的概率触发,一个是降级etcd版本时如果开启了鉴权,在K8s场景下较大概率触发。在具体探讨这两个bug前,咱们先看看在K8s场景下etcd数据不统一会导致哪些问题呢? •数据不统一最恐怖之处在于client写入是胜利的,但可能在局部节点读取到空或者是旧数据,client无奈感知到写入在局部节点是失败的和可能读到旧数据 •读到空可能会导致业务Node隐没、Pod隐没、Node上Service路由规定隐没,个别场景下,只会影响用户变更的服务 •读到老数据会导致业务变更不失效,如服务扩缩容、Service rs替换、变更镜像异样期待,个别场景下,只会影响用户变更的服务 •在etcd平台迁徙场景下,client无奈感知到写入失败,若校验数据一致性也无异样时(校验时连贯到了失常节点),会导致迁徙后整个集群全面故障(apiserver连贯到了异样节点),用户的Node、部署的服务、lb等会被全副删除,重大影响用户业务 首先第一个不统一bug是重启etcd过程中遇到的,人工尝试复现屡次皆失败,剖析、定位、复现、解决这个bug之路几经挫折,过程很乏味并充斥挑战,最终通过我对关键点减少debug日志,编写chaos monkey模仿各种异样场景、边界条件,实现复现胜利。最初的真凶居然是一个受权接口在重启后重放导致鉴权版本号不统一,而后放大导致多版本数据库不统一, 局部节点无奈写入新数据, 影响所有v3版本的3年之久bug。 随后咱们提交若干个相干pr到社区, 并全副合并了, 最新的etcd v3.4.9[1],v3.3.22[2]已修复此问题, 同时google的jingyih也曾经提K8s issue和pr[3]将K8s 1.19的etcd client及server版本升级到最新的v3.4.9。 第二个不统一bug是在降级etcd过程中遇到的,因etcd短少要害的谬误日志,故障现场无效信息不多,定位较艰难,只能通过剖析代码和复现解决。然而人工尝试复现屡次皆失败,于是咱们通过chaos monkey模仿client行为场景,将测试环境所有K8s集群的etcd调配申请调度到咱们复现集群,以及比照3.2与3.3版本差别,在可疑点如lease和txn模块减少大量的要害日志,并对etcd apply request失败场景打印谬误日志。 通过以上措施,咱们比拟快就复现胜利了, 最终通过代码和日志发现是3.2版本与3.3版本在revoke lease权限上呈现了差别,3.2无权限,3.3须要写权限。当lease过期的时候,如果leader是3.2,那么申请在3.3节点就会因无权限导致失败,进而导致key数量不统一,mvcc版本号不统一,导致txn事务局部场景执行失败等。最新的3.2分支也已合并咱们提交的修复计划,同时咱们减少了etcd外围过程失败的谬误日志以进步数据不统一问题定位效率,欠缺了降级文档,具体阐明了lease会在此场景下引起数据不一致性,防止大家再次采坑。 ...

July 14, 2020 · 2 min · jiezi

Pod-就地升级4如何判断Pod就地升级完成

上一章咱们讲了,kubelet如何通过计算容器的hash来判断是否须要降级容器。 本文次要讲如何判断Pod就地降级实现。 在ContainerStatus中不仅有hash filed。还记录了ImageID filed。 // Status represents the status of a container.type Status struct { // ID of the container. ID ContainerID // Name of the container. Name string // Status of the container. State State // Creation time of the container. CreatedAt time.Time // Start time of the container. StartedAt time.Time // Finish time of the container. FinishedAt time.Time // Exit code of the container. ExitCode int // Name of the image, this also includes the tag of the image, // the expected form is "NAME:TAG". Image string // ID of the image. ImageID string // Hash of the container, used for comparison. Hash uint64 // Number of times that the container has been restarted. RestartCount int // A string explains why container is in such a status. Reason string // Message written by the container before exiting (stored in // TerminationMessagePath). Message string}对于ImageID的更加具体的讲述,大家能够参考这个系列文章的第一篇。 ...

July 11, 2020 · 2 min · jiezi

谷歌将-Istio-商标移交-OUCIBM-表示失望

作者:Bach(才云)校对:bot(才云)随着以 Kubernetes 为根底构建的容器生态走向欠缺,越来越多开发者开始尝试将围绕容器生态开发的独立我的项目用于大规模落地实际,以扭转软件应用的开发和部署形式。这之中,开源尽管是很多我的项目的对立个性,但不同我的项目在凋谢治理水平上仍存在差别——其中最具争议的莫过于 Knative 和 Istio。 昨天,谷歌正式发表将开源服务网格 Istio 我的项目商标的所有权移交至 Open Usage Commons(OUC),由后者负责商标中立且独立的治理。此举宣告着 Istio 商标“归属权”的尘埃落定,但在很多人看来,围绕 Istio 的争议还远未解决。 Google 将 Istio 商标移交至 OUC 对于开源我的项目的可持续性倒退而言,自在且偏心地应用开源我的项目商标是一件十分重要的事件。尤其像 Istio 这样用户基数宏大的我的项目,尽管开发者基于 Apache 2.0 许可能够复制、批改、公布、应用我的项目的源代码,但他们不能轻易应用 Istio 的商标,这就导致了企业和集体开发者对我的项目应用产生了不确定性,也给社区扩张带来了不良影响。 Google 将 Istio 捐给 OUC 的本意,就是为了解决 Istio 商标的治理问题。 OUC 是谷歌昨天发动建设的一个独立组织,旨在通过商标治理和一致性测试来为开源我的项目提供治理和领导。目前该组织次要为三个 Google 开源的我的项目托管商标: Angular,一个用于挪动设施和台式机的 Web 应用程序框架;Gerrit,一个基于 Web 的团队代码合作工具;Istio,一个用于管制负载平衡、访问控制、指标、日志记录以及服务到服务的通信的服务网格我的项目。接手 Istio 后,OUC 将与我的项目领导委员会独特制订商标使用指南,不便社区对立应用 Istio 我的项目商标。换言之,有了 OUC 反对,将来 Istio 的商标将能够被自在偏心地应用,同时我的项目维护者也能够专一于技术社区的壮大和创立更多我的项目成绩。 从久远角度看,Google 此举对于增强我的项目维护者、生态系统合作伙伴与开发人员对于 Istio 倒退的信念是有不少助益的,也有不少人置信, OUC 将来会成为开源组织的重要组成部分。 但也有人不是这么想的…… IBM:咱们很悲观 尽管把开源我的项目捐献给中立组织在社区称得上是件“脍炙人口”的事,但在 Google 的申明公布后,作为对 Istio 做出过重大贡献的企业,IBM 却立刻发文示意不满: ...

July 10, 2020 · 1 min · jiezi

K8S通过Ingress和外部负载均衡暴露服务

一. 背景常识Kubernetes 通过 Ingress 裸露服务有两种计划: 将服务的域名间接指向到其中一台 worker 节点上. 这种形式将流量集中到这一台 worker 节点上, 容易引起单点故障, 故只实用于开发, 测试, 和Demo环境. 示意图如下:将服务的域名指向独立负载平衡服务到所有 worker 节点, 而 Ingress 会监听所有 worker 节点上的流量并进行相应的散发, 从而保障正确的服务. 在这种计划下, 即使咱们不是所有的节点都启动了该服务的容器, Ingress也会正确散发. 比方咱们咱们有 3 个 worker 节点: ttg12 / ttg13 / ttg14, 而服务对应的 Deployment 中设置的 replica=2, 也就是只启动2个正本. 假如这2个容器启动在 ttg12 和 ttg13 上. 这时候, 负载平衡服务器上转发的流量也会打到 ttg14 上, 尽管这个节点自身并没有对应的 pod, 但通过 Ingress, 也能失常地提供服务. 示意图如下:二. 部署本文示例部署一个 lb-tomcat9.faceless.cn 的域名指向 负载平衡服务器, 并通过 Ingress 提供服务. 2.1 部署 Deployment 和 Service本地新建文件 lb-tomcat9-svc.yaml: ...

July 9, 2020 · 2 min · jiezi

进击的-Kubernetes-调度系统一Kubernetes-scheduling-framework

简介: 阿里云容器服务团队联合多年 Kubernetes 产品与客户反对教训,对 Kube-scheduler 进行了大量优化和扩大,逐渐使其在不同场景下仍然能稳固、高效地调度各种类型的简单工作负载。《进击的 Kubernetes 调度零碎》系列文章将把咱们的教训、技术思考和实现细节全面地展示给 Kubernetes 用户和开发者,冀望帮忙大家更好地理解 Kubernetes 调度零碎的弱小能力和将来倒退方向。 作者 | 王庆璨(阿里云技术专家)、张凯(阿里云高级技术专家) 原文链接:点击这里 导读:阿里云容器服务团队联合多年 Kubernetes 产品与客户反对教训,对 Kube-scheduler 进行了大量优化和扩大,逐渐使其在不同场景下仍然能稳固、高效地调度各种类型的简单工作负载。《进击的 Kubernetes 调度零碎》系列文章将把咱们的教训、技术思考和实现细节全面地展示给 Kubernetes 用户和开发者,冀望帮忙大家更好地理解 Kubernetes 调度零碎的弱小能力和将来倒退方向。 前言Kubernetes 曾经成为目前事实标准上的容器集群治理平台。它为容器化利用提供了自动化部署、运维、资源调度等全生命周期治理性能。通过 3 年多的疾速倒退,Kubernetes 在稳定性、扩展性和规模化方面都有了长足进步。尤其是 Kubernetes 管制立体的外围组件日臻成熟。而作为决定容器是否在集群中运行的调度器 Kube-scheduler,更是因为长久以来体现稳固,且已能满足大部分 Pod 调度场景,逐步不被开发人员特地关注。 随同着 Kubernetes 在私有云以及企业外部 IT 零碎中广泛应用,越来越多的开发人员尝试应用 Kubernetes 运行和治理 Web 利用和微服务以外的工作负载。典型场景包含机器学习和深度学习训练任务,高性能计算作业,基因计算工作流,甚至是传统的大数据处理工作。此外,Kubernetes 集群所治理的资源类型也更加丰盛,不仅有 GPU,TPU 和 FPGA,RDMA 高性能网络,还有针对畛域工作的各种定制加速器,比方各种 AI 芯片,NPU,视频编解码器等。开发人员心愿在 Kubernetes 集群中能像应用 CPU 内存那样简略地申明和应用各种异构设施。 总的来说,围绕 Kubernetes 构建一个容器服务平台,对立治理各种新算力资源,弹性运行多种类型利用,最终把服务按需交付到各种运行环境(包含公共云、数据中心、边缘节点,甚至是终端设备),未然成为云原生技术的发展趋势。 晚期计划首先,让咱们来理解一下 Kubernetes 社区都有过哪些晋升调度器扩大能力的计划。 要对立治理和调度异构资源与更多简单工作负载类型,首先面对挑战的就是 Kube-scheduler。在 Kubernetes 社区里对于晋升调度器扩大能力的探讨始终一直。sig-scheduling 给出的判断是,越多功能退出,使得调度器代码量宏大,逻辑简单,导致保护的难度越来越大,很多 bug 难以发现、解决。而对于应用了自定义调度的用户来说,跟上每一次调度器性能更新,都充斥挑战。 ...

July 9, 2020 · 4 min · jiezi

使用-Kubernetes-最容易犯的-10-个错误

作者:Tj Blogumas翻译:Bach(才云) 校对:星空下的文仔(才云)、bot(才云) 在多年应用 Kubernetes 的过程中,咱们接触了相当多的 K8s 集群,同样也犯了许多谬误。本文就介绍了那些最容易也最常犯的 10 个谬误,并探讨了要如何解决。 资源申请和限度 这相对是犯错榜单的第一名。设置 CPU 申请有两种常见谬误:不设置或者设置的很低。尽管这样能够在每个节点上包容更多的 Pod,但会导致节点的适度应用。在高需要期间,节点的 CPU 会被齐全占用,工作负载取得的申请资源会受到 CPU 限度,从而导致应用程序提早、超时等状况。 不设置 CPU  申请的配置: resources: {}CPU 申请设置很低的配置: resources:另一方面,即便节点的 CPU 没有充分利用,如果设置了不必要的 CPU 限度同样会限度 Pod,这也会导致提早减少。 内存的适量应用一样会带来许多问题。达到 CPU 限度值会导致提早,而达到内存限度值,Pod 会被间接杀死,这就像是 OOMkill,一个内存不足时会主动杀死过程的机制。如果不想产生这样的事件,就不要适度应用内存,而应该应用 Guaranteed QoS,设置内存申请值等于限度值。 Burstable QoS 下的资源设置: resources:Guaranteed QoS 下的资源设置: resources:在设置资源时,咱们能够应用 metrics-server 查看容器以后 CPU 和内存的应用状况。如果它曾经在服务器端运行,能够运行以下命令: kubectl top pods 通过显示的以后应用状况,咱们就能够大抵理解资源状况了。如果想要及时查看状况指标,例如峰值,昨天晚上的 CPU 应用状况等,咱们能够应用 Prometheus、DataDog 等。它们会从 metrics-server 中获取指标并进行存储,而后咱们就能够查问或绘制图形。另外 ,VerticalPodAutoscaler 工具能够帮忙咱们自动化地查看 CPU、内存的应用状况,并依据状况从新设置新的申请值和限度。 liveness 和 readiness 探针的设置 ...

July 9, 2020 · 2 min · jiezi

Kubernetes-worknode的内核参数参考

集体再理论过程中踩坑后的Kubernetes worknode的内核参数调整,仅供参考▶ cat etcsecuritylimits.conf* soft nofile 100000* hard nofile 100000▶ cat etcsysctl.dkubernetes.conf net.bridge.bridge-nf-call-iptables = 1net.bridge.bridge-nf-call-ip6tables = 1net.ipv4.ip_forward = 1net.ipv4.tcp_tw_recycle = 0vm.swappiness = 0vm.overcommit_memory = 1vm.panic_on_oom = 0fs.inotify.max_user_instances = 8192fs.inotify.max_user_watches = 1048576fs.file-max = 52706963fs.nr_open = 52706963net.ipv6.conf.all.disable_ipv6 = 1net.netfilter.nf_conntrack_max = 2310720net.ipv4.ip_nonlocal_bind = 1net.nf_conntrack_max = 1048576net.ipv4.tcp_max_syn_backlog = 8096

July 8, 2020 · 1 min · jiezi

K8S-Ingress控制器两个实现版本kubernetesingress-和-ingressnginx的区别

K8s 有2个基于 Nginx 的 Ingress 控制器实现版本: 一个是 nginx实现版本 nginxinc/kubernetes-ingress, 另一个是 k8s实现版本 kubernetes/ingress-nginx. 在这篇文章里, 我们将介绍两者实现的核心差异. 这些信息可以帮助你根据需要选择恰当的实现, 或者从其中一个迁移至另外一个. 我当前用的哪个?如果你不确定你当前在使用的是哪个实现版本, 可以检查当前在运行的 Ingress 控制器的容器镜像来查看. 其中 nginxinc/kubernetes-ingress 实现版本的 Docker 镜像是发布在 DockerHub 的 nginx/nginx-ingress. [译者补充] 我们可以通过如下命令查看: $ sudo docker images | grep ingress[sudo] password for faceless:nginx/nginx-ingress 1.5.5 1e674eebb1af 9 months ago 161MB上面的输出显示我们当前使用的 nginx/nginx-ingress 实现. 核心差异下面的表格总结了两个 Ingress 控制器实现的核心差异. 注意这个表格右边两列都是关于nginx实现版本的控制器, 他们是分别针对 Nginx 和 Nginx Plus的. 有关更多 Nginx Plus 相关的 Nginx实现版本的信息, 可以查看这里. 特性K8S 实现版本Nginx 实现版本 (NGINX)Nginx 实现版本 (NGINX Plus)基础------作者K8S 社区Nginx 公司和社区Nginx 公司和社区Nginx版本包含一些三方模块的定制的 Nginx 版本Nginx 官方版本Nginx Plus商业支持N/AN/A包含通过Ingress资源配置负载均衡------合并同一host的Ingress规则支持通过 Mergeable Ingresses 支持通过 Mergeable Ingresses 支持HTTP负载均衡扩展 -- 注解方式见 K8S 支持的注解见 Nginx 支持的注解见 Nginx 支持的注解HTTP负载均衡扩展 -- ConfigMap 方式见 K8S 支持的 ConfigMap 主键见 Nginx 支持的 ConfigMap 主键见 Nginx 支持的 ConfigMap 主键TCP/UDP通过 ConfigMap 支持通过 ConfigMap (原生 NGINX 配置) 支持通过 ConfigMap (原生 NGINX 配置) 支持Websocket支持通过注解支持通过注解支持TCP SSL Passthrough通过 ConfigMap 支持不支持不支持JWT 验证不支持不支持支持Session 持久化通过三方库支持不支持支持金丝雀测试 (通过 header, cookie, weight)通过注解支持通过定制的资源支持通过定制的资源支持配置模板 *1见 模板见 模板见 模板通过定制化资源配置负载均衡配置------HTTP负载均衡不支持见 VirtualServer 和 VirtualServerRoute 资源见 VirtualServer 和 VirtualServerRoute 资源部署------命令行参数 *2见 K8S 版 参数列表见 Nginx 版 参数列表同左默认 Server 的 TLS 证书和秘钥必需(命令行参数) / 自动生成必需(命令行参数)必需(命令行参数)Helm Chart支持支持支持运维------上报 Ingress 控制器的 IP地址到Ingress资源支持支持支持扩展的状态通过三方模块支持不支持支持Prometheus 整合支持支持支持动态配置 endpoints (无需重新加载配置)通过三方模块支持不支持支持注释: ...

July 7, 2020 · 1 min · jiezi

解决k8s执行kubeadm-join遇到could-not-find-a-JWS-signature的问题

当使用kubectl join往Kubernetes集群添加worker节点, 如果遇到以下异常 (比如我们想把 ttg13 节点加入当前只有一个单master节点 ttg12 的集群中): $ sudo kubeadm join ttg12:6443 --token lbe5im.g79f9kxyyxdf2c9s --discovery-token-ca-cert-hash sha256:e4509816d73510fd6e008eba43d11b5807cd3de9f562dacd0dd2582c74eecafc# === 以下为输出 ===W0706 18:56:04.310137 21432 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.[preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/error execution phase preflight: couldn't validate the identity of the API Server: could not find a JWS signature in the cluster-info ConfigMap for token ID "lbe5im"To see the stack trace of this error execute with --v=5 or higher这个问题是在kube-public下的 configmap 的 cluster-info 中没有JWS签名, 本质上是 token 过期. ...

July 6, 2020 · 2 min · jiezi

混合kubebuilder与code-generator编写CRD

使用Kubebuilder+k8s.io/code-generator编写CRD。 本项目代码在 这里。 概览和k8s.io/code-generator类似,是一个码生成工具,用于为你的CRD生成kubernetes-style API实现。区别在于: Kubebuilder不会生成informers、listers、clientsets,而code-generator会。Kubebuilder会生成Controller、Admission Webhooks,而code-generator不会。Kubebuilder会生成manifests yaml,而code-generator不会。Kubebuilder还带有一些其他便利性设施。Resource + Controller = Operator,因此你可以利用Kubebuilder编写你自己的Operator。 如果你不想做Operator,如果你不会直接or间接生成Pod,只是想存取CRD(把K8S当作数据库使用)。那你可以使用Kubebuilder生成CRD和manifests yaml,再使用code-generator生成informers、listers、clientsets。 本文讲的就是这个方法。 准备工作:安装Kubebuilder参考这里安装kubebuilder。 第一步:初始化项目MODULE=example.com/foo-controllergo mod init $MODULEkubebuilder init --domain example.comkubebuilder edit --multigroup=true会生成以下文件: .├── Dockerfile├── Makefile├── PROJECT├── bin│   └── manager├── config│   ├── certmanager│   ├── default│   ├── manager│   ├── prometheus│   ├── rbac│   └── webhook├── hack│   └── boilerplate.go.txt└── main.go第二步:生成Resource和manifestskubebuilder create api --group webapp --version v1 --kind GuestbookCreate Resource [y/n]yCreate Controller [y/n]n会生成以下文件go代码和manifests文件: .├── apis│   └── webapp│   └── v1│   ├── groupversion_info.go│   ├── guestbook_types.go│   └── zz_generated.deepcopy.go└── config    ├── crd    │   ├── kustomization.yaml    │   ├── kustomizeconfig.yaml    │   └── patches    │   ├── cainjection_in_guestbooks.yaml    │   └── webhook_in_guestbooks.yaml    ├── rbac    │   ├── guestbook_editor_role.yaml    │   ├── guestbook_viewer_role.yaml    └── samples       └── webapp_v1_guestbook.yaml添加文件apis/webapp/v1/rbac.go,这个文件用生成RBAC manifests: ...

July 6, 2020 · 2 min · jiezi

MacOS上安装本地Kubectl管理集群

在测试环境或者比较小的集群中, 本地电脑和 Kubernetes 集群处于同一局域网内, 那么就可以通过在本地电脑上安装 kubectl , 直连 K8s master 并管理 k8s 集群. 一. 本地安装kubectlMacOS 下可通过 brew install 安装: $ brew install kubectl当然也可以直接下载: $ curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"$ chmod +x kubectl$ sudo mv ./kubectl /usr/local/bin/kubectl查看是否可正常使用: $ kubectl version二. 拉取配置文件到本地默认情况下, kubectl 读取 $HOME/.kube/config 作为配置文件. 另外, 也可以通过两种方式为 kubectl 指定配置文件: 环境变量 KUBECONFIG命令行参数 --kubeconfig本例我们采取$HOME/.kube/config 作为配置文件的方案. 在 k8s master 上拉取配置文件 /etc/kubernetes/admin.conf 到本地 ~/.kube/config. 本 demo 的配置文件内容如下: apiVersion: v1clusters:- cluster: certificate-authority-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tL......JJVkFURSBLRVktLS0tLQo= server: https://192.168.31.12:6443 name: kubernetescontexts:- context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetescurrent-context: kubernetes-admin@kuberneteskind: Configpreferences: {}users:- name: kubernetes-admin user: client-certificate-data: T0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0......VSVElGSUNBVEUtLS0tLQo= client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tL......JJVkFURSBLRVktLS0tLQo=注意: 如果配置文件中 server 的地址是 IP (比如上文中的192.168.31.12), 那么需要保证从本地能访问到该 IP; 如果是 hostname 且非正式域名, 那么在本地 hosts 文件中增加一条记录. ...

July 4, 2020 · 1 min · jiezi

安装Kuboard管理Kubernetesk8s

一. 背景知识通过可视化管理后台, 管理 Kubernetes 会更方便. 除了官方的Dashboard之外, 还有许多其他第三方开源的管理后. 其中 Kuboard 是一款比较优秀的国内开源管理后台. 相比于 Kubernetes Dashboard, Kuboard 更倾向于微服务配置. Kuboard 具有以下特性: GitLab/GitHub 单点登录集成RBAC 权限管理工作负载编辑器名称空间导出/导入二. 前提条件安装 Kuboard 时, 我们已经有一个 Kubernetes 集群. 以下任何形式安装的集群都可以: kubeadm 安装(或者基于 kubeadm 的衍生工具, 如 Sealos等);二进制安装;阿里云、腾讯云等公有云托管集群;其他。三. 安装通过以下命令: $ kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml$ kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.6/metrics-server.yaml查看 Kuboard 运行状态: $ kubectl get pods -l k8s.kuboard.cn/name=kuboard -n kube-systemNAME READY STATUS RESTARTS AGEkuboard-7bb89b4cc4-p5l2p 1/1 Running 0 179m如果为Running, 表示已成功启动. 否则使用kubectl describe查看失败原因. 墙内很有可能存在无法Pulling image的问题, 参考: 为什么我不能获取到镜像,ImagePullBackoff. ...

July 4, 2020 · 1 min · jiezi

Kubernetes插件管理工具krew安装和使用

一. 安装参考官方文档. MacOS和Linux上可通过如下命令安装: ( set -x; cd "$(mktemp -d)" && curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.{tar.gz,yaml}" && tar zxvf krew.tar.gz && KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" && "$KREW" install --manifest=krew.yaml --archive=krew.tar.gz && "$KREW" update)安装完成后, 将$HOME/.krew/bin添加到PATH环境变量中, 可以通过在.bashrc或.zshrc文件中添加如下脚本实现: export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"验证安装成功: $ kubectl krew二. 使用参考: 官方文档QuickStart. 2.1 krew update - 更新本地数据库类似于'apt update'. $ kubectl krew updateUpdated the local copy of plugin index.2.2 krew search - 搜索插件# 列出全部可用插件$ kubectl krew search...# 搜索指定插件$ kubectl krew search access-matrixNAME DESCRIPTION INSTALLEDaccess-matrix Show an RBAC access matrix for server resources no2.3 krew install - 安装插件$ kubectl krew install access-matrixUpdated the local copy of plugin index.Installing plugin: access-matrix...2.4 krew XXX - 使用插件# 使用access-matrix插件$ kubectl access-matrix2.5 krew upgrade - 升级全部插件$ kubectl krew upgrade2.6 krew uninstall - 卸载插件$ kubectl krew uninstall access-matrix...三. 插件列表全部插件列表官方地址. ...

July 3, 2020 · 2 min · jiezi

Pod健康检查和服务可用性检查

概述Kubernetes对Pod的健康状态可以通过两类探针来检查,kubelet定期执行这两类探针来诊断容器的健康状况。 LivenessProbe探针:用于判断容器是否存活(Running状态),如果LivenessProbe探针检测到容器不健康,则kubelet会杀掉该容器并且根据容器的重启策略执行相应处理。如果一个容器不包含LivenessProbe探针,那么kubelet认为该容器的LivenessProbe探针返回的值永远是Success。ReadinessProbe探针:用于判断容器服务是否可用(Ready状态),达到Ready状态的Pod才可以接受请求。对于被Service管理的Pod,Service和Pod Endpoint的关联关系也将基于Pod是否能被Ready进行设置。如果运行过程中Ready状态变为Flase,则系统将其自动从Service的后端Endpoint列表中隔离出去,后续再把恢复到Ready状态的Pod加回后端Endpoint列表。这样就能保证客户端在访问Service时不回被转发到服务不可用的Pod实例上。实现方式LivenessProbe探针和ReadinessProbe探针都可以配置以下三种实现方式: ExecAction在容器内部执行一个命令,如果该命令的返回码为0,则表明容器健康。 apiVersion: v1kind: Podmetadata: labels: test: liveness name: liveness-execspec: containers: - name: liveness image: k8s.gcr.io/busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 //启动容器后进行首次检查的等待时间 periodSeconds: 5 //监控检查发送请求后等待响应的超时时间。当超时发生时,kubelet会认为容器已经无法提供服务,将会重启该容器。 为了执行探测,kubelet cat /tmp/healthy在目标容器中执行命令,如果命令成功,则返回0,并且kubelet认为该容器是活动的且健康的。 容器启动时,它将执行以下命令 /bin/sh -c "touchu /tmp/healthy;sleep 30;rm -rf /temp/healthy;sleep 600 在容器寿命的前30s内,有一个/tmp/healthy文件。因此在前30s内,该命令 cat /tmp/healthy将返回成功代码,30s后,cat /tmp/healthy将返回失败代码。 TCPGetActionapiVersion: v1kind: Podmetadata: labels: test: liveness name: liveness-httpspec: containers: - name: liveness image: k8s.gcr.io/liveness args: - /server livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome initialDelaySeconds: 3 periodSeconds: 3 //每三秒执行一个活动探测为了执行探测,kubelet将HTTP GET请求发送到在容器中运行并且正在侦听端口8080的服务器。如果服务器/healthz路径的处理程序返回成功代码,则kubelet会认为该容器处于活动状态且运行状态良好。 ...

July 3, 2020 · 1 min · jiezi

Kubernatek8s常用命令

创建一个容器kubectl runfaceless@ttg12:~/tmp$ kubectl run --image=nginx:alpine nginx-app --port=8180pod/nginx-app created获取当前容器列表kubectl get类似于docker ps,查询资源列表。 faceless@ttg12:~/tmp$ kubectl get podsNAME READY STATUS RESTARTS AGEnginx-app 1/1 Running 0 9m52s如果容器创建后,状态一直Pending(未正常启动至Running状态),那么可以用下面kubectl describe查看具体的原因是什么。 查看指定容器状态kubectl describe类似于docker inspect,获取资源的详细信息。无论何时,只要遇到pod有问题,都先describe看下pod的状态。 faceless@ttg12:~/tmp$ kubectl describe pods nginx-appName: nginx-appNamespace: defaultPriority: 0Node: ttg12/192.168.199.212Start Time: Thu, 02 Jul 2020 10:53:06 +0800Labels: run=nginx-appAnnotations: <none>Status: PendingIP:IPs: <none>Containers: nginx-app: Container ID: Image: nginx:alpine Image ID: Port: 8180/TCP Host Port: 0/TCP State: Waiting Reason: ContainerCreating Ready: False Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-b79fd (ro)Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled TrueVolumes: default-token-b79fd: Type: Secret (a volume populated by a Secret) SecretName: default-token-b79fd Optional: falseQoS Class: BestEffortNode-Selectors: <none>Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300sEvents: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 59s (x5 over 5m12s) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate. Normal Scheduled 20s default-scheduler Successfully assigned default/nginx-app to ttg12 Normal Pulling 18s kubelet, ttg12 Pulling image "nginx:alpine"在容器内执行一个命令kubectl exec类似于docker exec,在容器内执行一个命令 ...

July 2, 2020 · 2 min · jiezi

从0到1学习边缘容器系列3应用容灾之边缘自治

边缘计算模式下,云端的控制中心和边缘端的设备之间网络环境较复杂,网络质量差次不齐没有保障。用户往往希望在弱网环境下,边缘容器能提供高可用的业务能力。TKE 边缘容器团队在弱网环境下提出了边缘自治功能。本文着重介绍了边缘容器在弱网环境下为了保证业务高可用而做的工作。 1问题背景 边缘计算使用的边缘设备数量庞大、分布全国各地,网络环境复杂,因特网、以太网、5G、WIFI 等形态均有可能。因此,云端的控制中心和边缘端的设备之间网络环境较复杂,网络质量差次不齐没有保障。 kubernetes 传统工作模式是所有组件 list-watch kube-apiserver,然后 reconcile 各种资源到期望状态。各节点的健康都强依赖于其与 kube-apiserver 通信的稳定。kubernetes 在传统的集群环境上工作很完美,因为大多数集群都能保证在一个局域网内。然而,在边缘计算的业务场景下,有一个稳定的网络环境着实是一件奢侈的事情。 在这样的背景下,如何保证边缘集群的业务高可用性以及服务高可用性?一直都是一个难题。为此我们腾讯云边缘容器团队(TKE@EDGE)设计了两个利器来专门啃下这块硬骨头,本篇将重点讲第一个利器——边缘自治。 (注:此文提到的网络环境,都是指节点与云端的网络环境,而不是业务运行所在环境。) 2需求举例 我们来以一个常见的厂房模型来介绍一下用户在弱网环境下使用传统 kubernetes 遇到的问题以及 TKE 边缘容器团队在此类场景下提出的解决方案。 厂房边缘计算模型 如上图所示,该案例采用的部署模式为:用户在腾讯云公有云上购买了几台 CVM 机器作为 master 节点,其上部署了 kube-apiserver、kube-controller-manager、kube-scheduler 三大组件。然后根据业务需求,为每一个厂房都创建多个边缘 worker 节点,部署 kubelet 和 kube-proxy 以及 dockerd。同厂房节点之间可以互相访问, 不同厂房节点网络不互通。比如两个分布在北京和广州的厂房的边缘节点虽然可以归属于同一个集群,但是它们之间的网络是不互通的。每个厂房内所有节点会通过公网连接至云端管控端,但是网络环境是不可靠的。 用户通过 kubernetes 管理平台进行workload的管理,master 与 worker 节点所在的厂房之间的网络环境网络环境是不能保证的,可能弱网A断网,网络B仍然正常。用户在这样的场景下,提出了几个需求: •节点即使和 master 失联,节点上的业务能继续运行 •保证如果业务容器异常退出或者挂掉,kubelet 能继续拉起 •保证节点重启后,业务能继续重新被拉起来 •用户在厂房内部署的是微服务,需要保证节点重启后,同一个厂房内的微服务可以访问 对于用户来说,这些诉求是他们的基本需求,也是其业务上云的关键因素。用户想要既享受 kubernetes 带来方便的管理运维,同时也要具备弱网环境下的容灾能力。这对传统标准 kubernentes 解决方案提出了挑战。 3标准 kubernetes 处理方式 我们来温习一下标准的 kubernentes 下,如果节点断网失联并且发生异常重启的行为后,会出现哪些现象呢? •失联的节点状态置为 NotReady 或者 Unknown 状态 ...

July 1, 2020 · 2 min · jiezi

Kubernetes-两步验证-使用-Serverless-实现动态准入控制

作者:CODING - 王炜1. 背景如果对 Kubernetes 集群安全特别关注,那么我们可能想要实现这些需求: 如何实现 Kubernetes 集群的两步验证,除了集群凭据,还需要提供一次性的 Token 校验?如何验证部署的镜像是否安全合规,使得仅允许部署公司内部镜像仓库的 Docker 镜像?如何实现对每一个 Deployment 动态注入 sidecar ,满足特定安全或业务需求?如何实现集群级的 imagePullSecrets ,当创建新的命名空间的时候,自动将 imagePullSecrets 注入到新的命名空间?本文以实现 Kubernetes 两步验证为例,利用 Kubernetes Admission 动态准入控制,同时借助 Serverless 实现一个两步验证的 Demo,使读者对动态准入控制和Serverless有较深入的了解。1.2 实现效果Token 两步验证失败,不允许部署 Token 两步验证成功,允许部署 2. 什么是 AdmissionAdmission 是在用户执行 kubectl 通过认证之后,在将资源持久化到 ETCD 之前的步骤,Kubernetes 为了将这部分逻辑解耦,通过调用 Webhook 的方式来实现用户自定义业务逻辑的补充。而以上过程,都是在用户执行 kuberctl 并等待 API Server 同步返回结果的生命周期内。 上图标注的 ① 和 ② 是 Admission 介入的工作流程,我们会发现有这些特点: Admission 工作在集群认证通过之后Admission 一共有两种:Mutating 和 Validating这两种具体的实现方式都是以 Webhook 实现的Admission 的操作对象可以是当前部署的用户、Yaml 内容等2.2 Admission MutatingMutating 的字面理解是“变异”的意思,真正的含义是,在资源持久化到 ETCD 之前,Mutating 控制器可以修改所部署的资源文件,比如给特定的 POD 动态增加 Labels,动态注入 sidecar 等。细心的读者会发现,Admission Mutating 在很多产品都被用到,比如 Istio 里面就是使用它来动态的给每一个容器注入 sidecar Envoy 容器来实现流量的劫持和管理。 ...

June 30, 2020 · 6 min · jiezi

在-K8S-大规模场景下-Service-性能如何优化

摘要:Kubernetes 原生的 Service 负载均衡基于 Iptables 实现,其规则链会随 Service 的数量呈线性增长,在大规模场景下对 Service 性能影响严重。本文分享了华为云在 Kubernetes service 性能优化方面的探索与实践。在企业业务推进过程中,不同业务领域的流量高峰通常都是在不同时间段来临,而应对这些不同时间到来的业务流量往往都需要大量的额外网络资源做保障。今天给大家带来我们在 Kubernetes Service 上的一些优化实践,这是一个网络相关的话题。首先,介绍Kubernetes的Service机制。现在 Kubernetes 中 Service 的三种模式,包括原来的 Userspace 和 Iptables,以及后来我们贡献的 IPVS;第二部分会介绍原来社区是如何使用 Iptables 来实现 Service 负载平衡的;第三部分主要是 Iptables 实现中存在的一些问题;接下来是如何使用 IPVS 来做 Service 的负载实现的;最后是一个对比。 Kubernetes的Service机制先看一下 Kubernetes 里面的 Service。在用 Kubernetes 之前,当我们有了容器网络之后,访问一个应用最直接的做法,就是客户端直接去访问一个 Backend Container。这种做法最直观和容易,同时问题也是显而易见的。当应用有多个后端容器的时候,怎么做负载均衡,会话保持怎么做,某个容器迁了之后 IP 跟着变怎么办,还有对应的健康检查怎么配,如果想用域名来做访问入口要怎么处理……这些其实就是 Kubernetes 的 Service 引入所要解决的问题。 01 Kubernetes Service 与 Endpoints 这张图表现了 Service 与其它几个对象的对应关系。首先是 Service,它保存的是服务的访问入口信息(如 IP、端口),可以简单理解为 Kubernetes 内置的一个 LoadBalancer,它的作用就是给多个 Pod 提供负载均衡。 图中是一个 Replication Controller 部署出来 2 个 pod 所对应的 Service。我们知道 RC 和 pod 的关系是通过 label-selector 来关联的,service 也是一样,通过 Selector 来匹配它所要做负载均衡的 Pod。实际上这中间还有一个对象,叫做 Endpoint,为什么要有这个对象呢?因为在实际应用中,一个 pod 被创建,并不代表它马上就能对外提供服务,而这个 pod 如果将被删除,或处于其他不良状态,我们都希望客户端的请求不被分发到这个无法提供服务的 pod 上。Endpoint 的引入,就是用来映射那些能对外提供服务的 pod。每个 Endpoints 对象的 IP 对应一个 Kubernetes 的内部域名,可以通过这个域名直接访问到具体的 pod。 ...

June 29, 2020 · 3 min · jiezi

Persistent-Volumes计算和存储分离

Kubernetes文档指出“管理存储与管理计算实例是一个不同的问题”。这概括了现代数据中心设计的基本原则,即从规划和部署角度出发,最好将计算和存储分开考虑。在Kubernetes中,通过诸如容器存储接口(CSI)之类的子系统,计算和存储的逻辑分离已变得越来越普遍。因此,与Kubernetes一起使用是一种强大的策略。 计算机存储本身只是一项技术。与其考虑存储,不如考虑数据及其用途。在理想的世界中,人们希望存储的数据如下: 正确性一致性可用性高性能耐用容灾可恢复性人们通常认为正确性是正确的,但是研究表明,在现实世界的系统中不应将正确性视为理所当然。一致性在某些应用程序中至关重要,但对于大多数数据中心数据使用而言,一致性通常会放宽。可用性和性能(访问数据并足够快地检索数据的能力)通常是存储系统需求的重点,其次是可恢复性。持久性通常包含在可恢复性下,并假设现实世界的系统最终会失败,并且必须实施一种方案来恢复丢失的数据。 今天,访问数据的性能通常与存储介质本身有关。 HDD用于纯顺序流访问,而SSD用于随机I / O工作负载。但这是一个过分的简化,因为固态存储的其他特征(例如低功耗,密度和对物理冲击的抵抗力(耐用性)再加上更高的性能,已使其在移动应用中无处不在。但是从数据中心的数据存储角度来看,HDD和SSD仍在使用中-当部署纯顺序工作负载时,HDD通常更具成本效益。用于高性能数据分析(顺序I / O工作负载)和NoSQL数据库(随机I / O工作负载)的横向扩展应用程序的兴起主要集中在使商品(行业标准)平台和媒体性能良好。 传统的企业应用程序已假定,如果您要存储数据,那么它应该始终可用。这导致了冗余,镜像和擦除编码技术,可以防止常见组件故障(风扇或机箱中的机械故障,介质故障等)。 虽然企业存储侧重于设计较小的高度调试的平台(设备,请考虑10个控制器),这些平台侧重于对应用程序透明的数据可用性技术,但现代的横向扩展,数据密集型应用程序将存储堆栈直接合并到应用程序中并且通常使用三重副本配置以提高可用性。与考虑擦除性能要求的采用擦除编码的工程存储系统相比,行业标准(即商品)存储介质和存储模块的经济性更倾向于采用三重副本方法。而应用程序存储部署的规模(认为有1000个控制器)导致了实现机架故障语义的战略以及通过简单地添加更多计算和存储来提高性能或容量的能力。 但是从某种意义上讲,这是没有意义的,因为当今企业中更常见的数据不可用的原因是计划在应用程序升级,网络和基础架构升级以及技术更新的停机时间。 如今,数据中心架构师可用来提高可用性的最大杠杆是将计算和存储分为独立管理的层,这些层通过无处不在的高速以太网网络连接。通过这种方法不仅可以解决可用性问题,而且可以通过提高经济效益和潜在地提高可操作性获得收益。 分离计算和存储所带来的好处有几个: 通过在服务器出现“故障”时消除重建/恢复来减少停机时间,只需将存储重新连接到新节点即可。通过部署较少数量的优化瘦客户端计算节点优化配置来消除SKU扩散。通过优化存储层的密度,形状因数和填充量,降低每插槽媒体的开销成本。最后,通过解耦生命周期,更快地在计算和存储层中采用新技术。Kubernetes已经发展为支持称为容器存储接口(CSI)的灵活存储接口,该接口允许任何存储提供商通过定义明确的接口提供服务。 CSI不赞成使用以前的树内存储提供程序方法,并向各种存储部署方法开放了Kubernetes。 CSI提供程序接口为Kubernetes定义了一个动态存储模型。在许多方面,CSI接口鼓励供应商为现有存储解决方案定义新接口,以在Kubernetes的控制下按需动态分配持久性存储卷。 CSI甚至将功能扩展到了传统企业存储解决方案。 CSI抽象提供了对计算和存储的必要和有益的分离,该分离支持上述物理分离方法。 CSI还允许专注于“网络存储”网络方面的较新的网络存储方法为Kubernetes提供健壮的解决方案,该解决方案更适合于Web规模数据应用程序的存储配置。 Web规模数据分析存储的Kubernetes部署要求是一个不断发展的领域。 Kubernetes提供了规模和编排功能以部署高性能数据分析应用程序。与重量更重的传统VM方法相比,轻量级容器模型更适合于高性能横向扩展数据分析应用程序。但是,根据特定的工作负载,其中许多应用程序是在假定直接访问本地HDD或SSD存储的情况下编写的。存在诸如可组合基础架构之类的方法来为网络存储提供本地驱动器的性能和行为。可组合基础架构还支持许多应用程序定义的应用程序中存储堆栈模型,并进行了正确配置和自动化,从而实现了机架故障语义。 CSI模型完全支持此类部署,从而为Kubernetes上的这些应用程序提供了高性能的解决方案。 支持持久存储的CSI接口是Kubernetes生态系统的最新成员。它已经导致了许多针对Web规模应用程序的网络存储解决方案。来年,这将是一个值得关注的空间。 PS: 本文属于翻译,原文

June 29, 2020 · 1 min · jiezi

K8S-生态周报-CoreDNS-发布-v170

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。CoreDNS v1.7.0 发布CoreDNS 本周发布了 v1.7.0 版本, 这是一个向后不兼容的版本。 主要包含了以下几个方面: #3776更好的 metrics 名称,其修改了大量的 metrics 名称,Dashborad 之类的都需要修改了。 例如: coredns_request_block_count_total -> coredns_dns_blocked_requests_total#3794 federation 插件已经被移除 (v1 Kubernetes federation);从 kubernetes 插件中删除了一些代码, 所以它不会作为外部插件构建;#3534 新的 dns64 插件,由外部转为内置插件,该插件提供了 DNS64 IPv6 地址转换机制;#3737 plugin/kubernetes: 移除了已经过期的 resyncperiod 和 upstream 选项;以上便是此版本中值得注意的变更,更多详细内容请参看其 ReleaseNote Helm v3.2.4 发布这是一个安全更新版本,主要是为了修正一个漏洞,该漏洞影响了 v3.2.4 之前所有 Helm v3 版本。漏洞号为 CVE-2020-4053 此漏洞的具体影响范围是,当通过 HTTP 的方式从远程来安装一个 Plugin 的时候,可能会发生文件目录的遍历攻击。攻击者可能会在恶意插件中包含相对路径,以此来将攻击文件复制到预期的文件目录之外。 这是一种很常见的攻击方法,在之前的「K8S 生态周报」文章中,我也介绍过类似的利用这种文件目录遍历的漏洞。 修正方式也很简单,对于文件的解压操作,判断是否包含相对路径,如果有,则抛出异常(这里主要是为了警示用户,其安装的内容中可能有恶意行为)。 对此版本感兴趣的朋友,可以直接下载 使用。 Istio v1.6.3 发布本周 Istio 发布了 v1.6.3 ,此版本的主要变更如下: ...

June 26, 2020 · 1 min · jiezi

Minikube运行在笔记本上的Kubernetes集群

前言Minikube是一个可以在本地电脑上运行Kubernetes的工具。Minikube会在笔记本电脑中的虚拟机上运行一个单节点的Kubernetes集群,让用户能对Kubernetes进行体验或者在之上进行Kubernetes的日常开发。 Windows,MacOS和Linux系统上都可以安装Minikube,不过在安装前需要确认系统的版本已经支持虚拟化(一般只要不是太老的系统版本都支持虚拟化) kubectl在电脑上安装Minikubne前需要先安装kubectl,它是Kubernetes的命令行工具,可以使用kubectl部署应用程序,检查和管理集群资源以及查看日志。 安装kubectl文章里我们演示的安装步骤都是macOs上的,如果是Linux和Windows系统只需要下载相应系统的二进制文件就行,我会在文章后边贴上官方的安装指南。 首先下载最新的稳定版本的kubectl二进制文件。 curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"为kubectl授予可执行权限,然后将可执行文件放到系统的PATH目录中 chmod +x ./kubectl && sudo mv ./kubectl /usr/local/bin/kubectl安装MiniKube如果你的macOS上没有安装虚拟机监控程序的话在第一次启动minikube的时候会自动选择安装HyperKit作为虚拟机驱动,如果是以前电脑上有安装过VirtualBox那么可以在Minikube启动时加上--vm-driver=virtualbox来选择虚拟机驱动。 安装minikube的过程跟kubectl的过程差不多,也是下载minikube的二进制文件,赋予可执行权限后将其放入系统环境变量PATH对应的目录中。 不过由于大家都知道的网络访问原因,很多朋友无法直接使用Kubernetes官方提供的minikube进行实验,所以这里选择使用阿里云提供minikube版本 curl -Lo minikube https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v1.11.0/minikube-darwin-amd64 \ && chmod +x minikube \ && sudo mv minikube /usr/local/bin/如果是Linux和Window系统,安装流程类似只是软件的版本不同,具体可以参照MiniKube的安装指南 运行Minikube启动minikube的方法非常简单,只要使用下面的命令 minikube start --image-mirror-country='cn' --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers' 在最新的Minikube中,已经提供了配置化的方式,可以帮助大家利用阿里云的镜像地址来获取所需的Docker镜像和配置。 测试Minikube下面我们通过minikube status命令查看一下它的运行状态测试我们安装的minikube。 ➜ minikube statusminikubetype: Control Planehost: Runningkubelet: Runningapiserver: Runningkubeconfig: Configured通过kubectl查看集群的一些信息。 ➜ kubectl get pods -ANAMESPACE NAME READY STATUS RESTARTS AGEkube-system coredns-67c766df46-59rtb 1/1 Running 0 17mkube-system coredns-67c766df46-jxmvf 1/1 Running 0 17mkube-system etcd-minikube 1/1 Running 0 16mkube-system kube-addon-manager-minikube 1/1 Running 0 16mkube-system kube-apiserver-minikube 1/1 Running 0 16mkube-system kube-controller-manager-minikube 1/1 Running 0 17mkube-system kube-proxy-ljppw 1/1 Running 0 17mkube-system kube-scheduler-minikube 1/1 Running 0 16mkube-system storage-provisioner 1/1 Running 0 17m➜ kubectl get nodesNAME STATUS ROLES AGE VERSIONminikube Ready master 18m v1.18.3➜ kubectl get namespacesNAME STATUS AGEdefault Active 18mkube-node-lease Active 18mkube-public Active 18mkube-system Active 18m接下来安装完Minikube后我们的电脑上就有了Kubernetes的基础运行环境,通过最近几篇关于Kubernetes的文章相信大家都对已经对Kubernetes有了初步的认识,不过都是概念性的知识,到现在来说Kubernetes还是一个比较抽象的东西,说实话这么学下去的话我会觉得太枯燥,需要一些实操性的练习给自己一些正反馈才能坚持下去。所以我准备尝试做一个简单的用Go语言写的应用程序的Docker镜像,把它放到本地电脑上的Kubernetes集群(Minikuebe)上运行。具体步骤会在下周推送的文章里告诉大家,祝大家假期愉快! ...

June 24, 2020 · 1 min · jiezi

如何为-Kubernetes-实现原地升级

简介: 原地升级一词中,“升级”不难理解,是将应用实例的版本由旧版替换为新版。那么如何结合 Kubernetes 环境来理解“原地”呢? 镜像下载、域名解析、时间同步请点击 阿里巴巴开源镜像站 一、概念介绍原地升级一词中,“升级”不难理解,是将应用实例的版本由旧版替换为新版。那么如何结合 Kubernetes 环境来理解“原地”呢? 我们先来看看 K8s 原生 workload 的发布方式。这里假设我们需要部署一个应用,包括 foo、bar 两个容器在 Pod 中。其中,foo 容器第一次部署时用的镜像版本是 v1,我们需要将其升级为 v2 版本镜像,该怎么做呢? 如果这个应用使用 Deployment 部署,那么升级过程中 Deployment 会触发新版本 ReplicaSet 创建 Pod,并删除旧版本 Pod。如下图所示: 在本次升级过程中,原 Pod 对象被删除,一个新 Pod 对象被创建。新 Pod 被调度到另一个 Node 上,分配到一个新的 IP,并把 foo、bar 两个容器在这个 Node 上重新拉取镜像、启动容器。 如果这个应该使用 StatefulSet 部署,那么升级过程中 StatefulSet 会先删除旧 Pod 对象,等删除完成后用同样的名字在创建一个新的 Pod 对象。如下图所示: 值得注意的是,尽管新旧两个 Pod 名字都叫 pod-0,但其实是两个完全不同的 Pod 对象(uid也变了)。StatefulSet 等到原先的 pod-0 对象完全从 Kubernetes 集群中被删除后,才会提交创建一个新的 pod-0 对象。而这个新的 Pod 也会被重新调度、分配IP、拉镜像、启动容器。 而所谓原地升级模式,就是在应用升级过程中避免将整个 Pod 对象删除、新建,而是基于原有的 Pod 对象升级其中某一个或多个容器的镜像版本: ...

June 24, 2020 · 3 min · jiezi

在采用K8S之前您必须了解的5件事情

作者简介 Christopher Tozzi,自2008年来以自由职业者的身份对Linux、虚拟化、容器、数据存储及其相关主题进行报道。 时至今日,Kubernetes已然成为风靡一时的容器编排调度工具,许多IT分析师均提出了企业应当在何时采用Kubernetes的深刻建议。然而,和所有其他的软件平台一样,Kubernetes并非是一个适用于所有人的灵丹妙药。我更倾向于认为人们在有些时候过分夸大了Kubernetes的作用,以至于他们产生了一种错觉:他们无法离开Kubernetes,而实际上,Kubernetes比他们真正的需求要复杂得多。 为了分析人们真正的需求与Kubernetes的匹配程度,我分析了企业在采用Kubernetes编排之前必须考虑的5个事情。 Kubernetes是什么?如果您关注容器,您可能会知道Kubernetes是一个用于容器编排的开源工具,它可以自动执行诸如启动容器、停止容器以及在同一个容器的不同实例之间的负载均衡等重要任务。 简而言之,Kubernetes的主要目的是最大限度地减少工程师必须手动执行的管理工作量,并通过简化容器操作,帮助企业大规模运行复杂的容器化应用程序。 决定是否采用Kubernetes的关键要素基于Kubernetes的设立初衷,如果您喜欢自动化,讨厌手动执行重复性的任务,那么Kubernetes无疑是您的极佳选择。 这是您决定是否采用Kubernetes的重要前提,但是,您不能仅根据这一“前提”就决定是否采用Kubernetes。在采用Kubernetes之前,您还需要考虑并权衡其他重要的因素。 1、Kubernetes的基础设施规模您的基础设施规模是其中一个决定Kubernetes是否能够很好地为您所用的关键要素。 Kubernetes的设计初衷是协调分布在真正庞大的环境中的容器,这往往意味着企业应当拥有数十台主机服务器。根据过往的实施经验,如果基础架构中的服务器少于50个,那么您可能没有足够的资源来利用Kubernetes的全部优势。 这并不是指Kubernetes无法在较小规模的基础设施上运行。实际上,如果您愿意,您可以在单个主机上运行Kubernetes。然而,由于Kubernetes其中的一个研发目的是:通过在数量庞大的集群中分布容器化应用程序提供高可用性,因此,如果您只有少量服务器,则无法享受到Kubernetes的某些价值。 除此之外,考虑到设置和维护Kubernetes的复杂性,如果您的基础设施规模较小,无法完全实现Kubernetes的高可用性承诺,那么或许您不应投入过多时间和精力在Kubernetes上。 对于较小的基础架构,您可以使用较为简单的容器编排工具,或者使用如AWS ECS等具有内置编排的基于云的容器服务。 2、Kubernetes操作系统环境Kubernetes主要是一种Linux技术。尽管Kubernetes可以用于管理托管Windows服务器上的容器化应用程序,这些应用程序作为Kubernetes服务器集群内的所谓工作节点运行。但托管Kubernetes核心服务的主要服务器或者说主节点必须是Linux。 因此,如果您的商店以Windows为中心,那么Kubernetes并非您的最佳选择。但是您可以选择Rancher轻松将Kubernetes的优势引入Windows,并且极大程度降低使用的复杂性。 3、安装和设置Kubernetes在决定采用Kubernetes之前,您还需要评估您可以在此项目上投入的工作时间。 普通的开放源代码版本的Kubernetes缺少内置的应用程序,也并未提供一种可以适用于所有默认配置的安装方式。在集群正常运行之前,您需要投入大量的时间从头开始编写及调整配置文件。因此,安装和配置Kubernetes的过程或许是一个令人生畏的过程,您需要投入大量的时间和精力。 部分Kubernetes发行版提供了交互式安装程序脚本,可以帮助您自动执行大部分设置过程。如果您选择Rancher等Kubernetes发行版,则有望在一两天内轻松完成配置及安装。 第三种选择是使用诸如Google Kubernetes Engine等云供应商解决方案,将Kubernetes作为托管服务在云上运行。在这种情况下,您可以自行选择安装及设置。但值得注意的一点是,在确定如何配置Kubernetes环境时,您的选择可能会受到限制。 您必须意识到最为关键的一点:不要低估配置Kubernetes的难度。在您真的要全身心投入Kubernetes之前,请确保您所付出的努力是值得的。另一方面,如果您无法确定为企业在生产集群上安装和部署Kubernetes的难度,您可以尝试使用K3s等轻量级Kubernetes发行版来进行测试,预估后续需要付出多少努力来进行Kubernetes的配置和设置。 4、Kubernetes和声明式配置管理Kubernetes采用了所谓的声明式配置管理方法,这就意味着,您需要自行编写配置文件来设置Kubernetes应用程序应当如何运行,而Kubernetes将自动指出如何使应用程序符合规范。 声明式配置管理与命令式配置管理相反,在命令式配置管理中,您可以自行配置应用程序的每个组件,并让其按照您所想要的方式运行。 声明式配置是Kubernetes在许多用户实例中如此强大和可伸缩的其中一个原因。您可以设置一次配置,并且根据需要多次应用它。 但是,如果您的配置需求不断变化,或者在工作负载或环境中的不同部分之间变化,那么您应当如何处理呢?在这种情况下,声明式配置管理将成为一个障碍,您将发现自己需要不断地调整先前认为是“一劳永逸”的配置文件。 因此,在您选择采用Kubernetes之前,您需要考虑应用程序的配置需求。只有当您所需要的配置相对通用且静态时,Kubernetes才是一个不错的选项。 5、Kubernetes和多云Rancher等部分Kubernetes发行版的主要功能之一,是单个Kubernetes部署可以编排多个集群,无论集群位于在不同的公有云还是私有云上。这一功能使Kubernetes成为协助控制多云架构复杂性的优秀工具。 在跨多云部署容器化应用程序,并且Kubernetes的设置和配置工作很合理时,多云上的Kubernetes是十分有意义的。 在这一因素中,您需要留意的是,在考虑是否以及何时采用Kubernetes时,应考虑您当前的多云战略以及多云扩展计划。 结 语Kubernetes是一个非常棒的工具,在正确设置的情况下,它可以产生巨大的价值。但是,它并没有达到杀手级应用程序的状态,因为它无法在所有用户实例中交付价值。在您被巨大的宣传攻势攻陷,并确定您无法离开Kubernetes之前,请清醒地对自己的需求进行评估,明确Kubernetes是否能在真正意义上帮助您更加有效、更加可靠地运行应用程序。

June 24, 2020 · 1 min · jiezi

从0到1学习边缘容器系列之-边缘应用管理

大家对使用Kubernetes管理应用已经比较熟悉,但是边缘场景下的应用部署和管理是否存在不同的需求呢?本文将和大家一起探讨边缘场景下常见的容器应用管理方案。 1边缘简单服务场景 在笔者接触过的边缘需求中部分用户业务场景比较简单,如:拨测服务。这种场景的特点是用户希望在每个节点部署相同的服务,并且每个节点起一个 pod 即可,这种场景一般推荐用户直接使用 daemonset 部署。关于 daemonset 的特点和使用方式读者可以阅读 kubernetes 官方文档。 2边缘单站点部署微服务场景 第二种场景是部署边缘 SAAS 服务,由于涉及客户商业机密,此处暂不举例。用户会在一个边缘机房内部署一整套微服务,包括账号服务、接入服务、业务服务、存储及消息队列,服务之间借助kubernetes的dns做服务注册和发现。这种情况下客户可以直接使用 deployment和service,其中最主要的困难不在于服务管理而是边缘自治能力。 关于deployment和service的使用方式读者可以阅读kubernetes 官方文档,关于TKE@edge 边缘自治能力我们将会在后续推出相关文章介绍。 3边缘多站点部署微服务场景 场景特点: •边缘计算场景中,往往会在同一个集群中管理多个边缘站点,每个边缘站点内有一个或多个计算节点。 •希望在每个站点中都运行一组有业务逻辑联系的服务,每个站点内的服务是一套完整的微服务,可以为用户提供服务 •由于受到网络限制,有业务联系的服务之间不希望或者不能跨站点访问 常规方案: 1.将服务限制在一个节点内 该方案特点: •服务以daemonset方式部署,以便每个边缘节点上均有所有服务的 pod。如上图所示,集群内有A、B两个服务,以daemonset部署后每个边缘节点上均有一个 Pod-A和Pod-B。 •服务通过localhost访问,以便将调用链锁定在同一个节点内。如上图所示,Pod-A和Pod-B之间以localhost访问。 该方案缺点: •每个服务在同一个节点内只能有一个 Pod,这是由于daemonset工作机制所限,对于需要在同一节点上运行多个 Pod的服务来说这个限制极为不便。 •Pod需要使用 hostnetWork模式,以便Pod之间可以通过localhost+port访问。这意味着需要用户很好地管理服务对资源使用,避免出现资源竞争,如端口竞争。 2.服务在不同站点叫不同的名字 该方案特点: •相同服务在不同站点叫不同的名字,以便将服务间的访问锁定在同一个站点内。如上图所示,集群内有A、B两个服务,在site-1中分别命名为 svr-A-1、Svc-B-1,在site-2中分别命名为 svr-A-2、Svc-B-2。 该方案缺点: •服务在不同站点名字不同,因而服务之间不能简单地通过服务名A和B来调用,而是在 site-1中用 Svc-A-1、Svc-B-1,在site-2中用 Svc-A-2、Svc-B-2。对于借助 k8s dns 实现微服务的业务极为不友好。 场景痛点: 1.k8s本身并不直接针对下述场景提供方案。 •首先是众多地域部署问题:通常,一个边缘集群会管理许多个边缘站点(每个边缘站点内有一个或多个计算资源),中心云场景往往是一些大地域的中心机房,边缘地域相对中心云场景地域更多,也许一个小城市就有一个边缘机房,地域数量可能会非常多;在原生k8s中,pod的创建很难指定,除非使用节点亲和性针对每个地域进行部署,但是如果地域数量有十几个甚至几十个,以需要每个地域部署多个服务的deployment为例,需要各个deployment的名称和selector各不相同,几十个地域,意味着需要上百个对应的不同name,selector,pod labels以及亲和性的部署yaml,单单是编写这些yaml工作量就非常巨大; •services服务需要与地域关联,比如音视频服务中的转码和合成服务,要在所属地域内完成接入的音视频服务,用户希望服务之间的相互调用能限制在本地域内,而不是跨地域访问。这同样需要用户同样准备上百个不同selector和name的本地域deployment专属的service的部署yaml; •一个更复杂的问题是,如果用户程序中服务之间的相互访问使用了service名,那么当前环境下,由于service的名称各个地域都不相同,对于用户而言,原来的应用甚至都无法工作,需要针对每个地域单独适配,复杂度太高。 2.另外,使用方为了让容器化的业务在调度方案上与之前运行在 vm或者物理机上的业务保持一致,他们很自然就想到为每个 pod 分配一个公网IP,然而公网IP数量明显是不够用的。 综上所述,原生k8s虽然可以变相满足需求1),但是实际方案非常复杂,对于需求2)则没有好的解决案。 ...

June 23, 2020 · 1 min · jiezi

6大服务网格工具比较

服务网格(Service mesh)已经不是一个新鲜概念,但它实现了连接运行在Kubernetes作为容器化平台之上的微服务,这使得服务网格的想法更加流行。如果没有服务网格,每个微服务都需要配置以接收(或发送)连接到其他需要与之通信的微服务,但服务网格完全改变了这一状况。 与此前需要手动配置以及投入大量的时间精力来维护微服务之间的连接所不同的是,开发人员现在可以创建一个网格,使得微服务彼此通信可靠、可控以及安全。Kubernetes和服务网格是相互作用的,主要是因为使用服务网格可以在不增加工作量的情况下,实现更复杂的容器化架构。 因此,有很多方式可以在Kubernetes顶层建立一个服务网格。在本文中,我们将比较一些你可以用于建立服务网格的工具,你可以分别了解到它们的优劣势进而选出最适合自己的服务网格工具。 与AWS环境完美适配:AWS App Mesh官网:https://aws.amazon.com/app-mesh/ 由于现在许多基于Kubernetes的应用程序和微服务都运行在Amazon Web Services环境中,所以很难不谈到AWS App Mesh。顾名思义,AWS App Mesh是亚马逊自己的服务网格,用于为Amazon services创建服务网格层。 作为亚马逊的产品,AWS App Mesh利用结合了Envoy的专有技术作为其服务代理。AWS App Mesh通过创建虚拟服务在相同的命名空间中连接服务。 在你的AWS环境中每个微服务都可以找到虚拟服务并使用它来与其他微服务通信。 AWS App Mesh与其他服务(例如EKS、Fargate和EC2)的无缝集成是其最强的优势,但在使用App Mesh的过程中存在一些限制。首先,你不能将App Mesh迁移到外部或者在多云设置中使用这一服务。 App Mesh还借助CloudWatch和AWS X-Ray来管理服务网格,这意味着你可以在不离开主仪表板的情况下完全控制该层。诸如支持mTLS和高级负载均衡的特性在App Mesh中也有,但是它不支持身份验证规则。 最流行的服务网格工具:Istio官网:https://istio.io/latest/zh/ Istio可能是最流行的Kubernetes服务网格工具,它最初由Lyft开发,但后来变成Lyft、Google和IBM联合开发。考虑到Kubernetes背后的公司是谷歌,那么Istio被广泛用于许多部署类型也并不奇怪了。 与App Mesh类似,Istio也将Envoy用作其服务代理,但它并没有限制你把Envoy作为唯一的ingress controller。Istio的独特之处在于它提供了巨大的灵活性。你可以将Istio用于其他的容器化平台,但其与Kubernetes的无缝衔接使其发挥的作用更大。 例如,Istio支持mesh扩展和多云网格,这两个特性在App Mesh和其他服务网格工具里都是没有的。Istio还可以处理流量访问控制以及负载均衡,就像它是为了执行这些任务而构建的一样。它甚至支持故障注入和延迟注入。 使用Istio的唯一缺点是你可能会对它提供的功能感到不知所措。如果你有足够的资源使用Istio处理服务网格层,这个工具有可能通过其功能简化最复杂的微服务架构。 独立的服务网格工具:Linkerd官网:https://linkerd.io/ 当Linkerd发布2.x版本时,它已经是一个十分流行的服务网格工具了。新版本受到了Kubernetes社区的欢迎,截止到2020年4月中旬,其2.7.1稳定版已经出炉。它完全是作为一个独立的服务网格工具来构建的,所以它并不依赖Envoy等第三方工具来管理,它甚至还包含了linkerd-proxy作为服务代理。 最近的升级还包括dashboard的改进和针对金丝雀部署的流量拆分功能的可视化。这使其成为实时监控和编排金丝雀和蓝绿部署的绝佳工具。 在保持独立的同时,Linkerd还与Ingress controller保持高度兼容性。实际上,Linkerd能够与你使用的任意Ingress controller一起工作,使它在这方面最为灵活。一个简单的linkerd inject命令就可以让服务网格与你的应用程序集成。 Linkerd2 也是高度优化的,安装仅需60秒。如果你正在寻找可以带来最佳性能的服务网格工具,那么Linkerd是你可以考虑尝试的。作为一个非侵入式的服务网格工具,Linkerd在部署之后并不需要进行大量的优化。开箱即用的配置足以支持复杂的微服务架构,并且能够防止重大工具。Linkerd通过mutual TLS(mTLS)加密来增强应用程序的安全性。 Linkerd也是一个专门为Kubernetes开发的工具。它可能不支持多云和多集群网格创建,但这丝毫不会减弱其作为Kubernetes实例的服务网格层的能力。除此之外,它也可以与OpenCensus配合使用,从而使跟踪和管理变得非常容易。 最年轻的服务网格工具:Kuma官网:https://kuma.io/ Kuma将Envoy作为服务代理并且支持任意ingress controller。这与Consul Connect十分类似(该工具我们稍后会介绍),但Kuma也有自己令人耳目一新的功能。而且这些新意可能是因为Kuma是这个列表中最新的工具。 不要被Kuma年轻的年龄所欺骗了,它不仅仅已经生产就绪,而且还具备了你所期望的服务网格工具的功能。它支持所有与OpenTracing兼容的所有后端并且允许你在需要时使用外部CA证书。不过,这一工具也存在不完善的地方——有一些功能是缺失的。 目前,在Kuma中没有办法进行基于路径或基于请求头的流量分割。它也不支持诸如流量访问控制和指标等功能。这些功能也许会在后续版本中引入,但现在你必须得手动制作代理模板来弥补这些功能的缺失。 但是,Kuma作为一个服务网格工具还是很有前途的,尽管目前它只是0.4.0版本,但其开发者十分关注社区的意见并且十分乐意满足用户的要求,从这个维度上看,这个工具无疑是极具竞争力的。 最适用于Consul环境的服务网格:Consul Connect官网:https://www.consul.io/ 由HashiCorp推出的Consul Connect可以与Envoy及其他各种服务代理一起工作,它还可以与任何ingress controller一起工作,这使其成为最容易集成到现有Kubernetes集群中的工具之一。 在任意Consul环境中Consul Connect都可以无缝衔接,但是它也只能在Consul环境中工作。虽然该服务网格工具提供了许多方便的功能,但它是为了能与其他HashiCorp产品使用而设计的。不过,这些工具的应用十分广泛。 从TCP到gRPC的一切都支持,此外这一工具还能与Kubernetes、VM甚至Nomads一起工具。网格扩展也是完全支持的,所以你可以拥有一个跨多个云服务和集群的环境,并且仍然具有一个支持微服务的功能强大的服务网格层。 Consul Connect需要改进的一个方面是监控。然而,你也可以整合其他监控工具,以便获得日志和每个路由的指标。你甚至可以集成诸如Prometheus和Grafana等工具来可视化你的监控数据。然后你只需要从你的服务代理中提取数据即可。 ...

June 23, 2020 · 1 min · jiezi

kubernetes部署建议持续跟新暂时想不起来

升级内核1. $ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org$ yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm$ yum list available --disablerepo=* --enablerepo=elrepo-kernel$ yum install -y kernel-lt-4.4.218-1.el7.elrepo --enablerepo=elrepo-kernel$ cat /boot/grub2/grub.cfg | grep menuentrygrub2-set-default "CentOS Linux (4.4.218-1.el7.elrepo.x86_64) 7 (Core)"$ grub2-editenv list$ reboot

June 23, 2020 · 1 min · jiezi

Linkerd-28发布更简单安全的多集群Kubernetes服务网格

今天我们高兴地宣布,Linkerd 2.8已经正式发布!新的版本为Linkerd引入了多集群扩展机制,使其能够跨Kubernetes集群建立连接,保证各集群的安全性与透明性,并可以与任意网络拓扑一同使用。我们认为,这项多集群扩展机制正是目前实现Kubernetes多集群安全连接的最佳选项。另外,2.8版本还为Linkerd引入add-on系统,帮助其进一步提升模块化水平;同时引入多项其他功能与稳定性改进。 1用Kubernetes的方式实现多集群Kubernetes Linkerd 2.8的全新多集群功能,意味着Linkerd现在能够以安全的、对应用程序完全透明且独立于网络拓扑之外的方式跨集群边界接入各项Kubernetes服务。这项多集群功能,旨在满足以下几项核心目标: 1.提供统一的信任域。源工作负载与目标工作负载的身份必须在集群边界内与跨集群边界处的每个步骤进行验证。 2.分离故障域。某一集群发生宕机,其他集群应该仍可正常运行。 3.支持异构网络。由于集群可以跨越不同云环境、VPC、本地数据中心及其组合,因此除网关连接之外、Linkerd不应引入任何L3/L4要求。 4.提供具备集群内通信能力的统一模型。Linkerd为集群内通信带来的可观察性、可靠性与安全性功能,也将扩展到新的跨集群通信体系当中。 与集群内连接一样,Linkerd的跨集群连接同样对应用程序代码完全透明。例如,集群west上的服务A可以将集群east上的服务C直接寻址为C.east的形式以实现直接通信;或者自动将其寻址为C.east,并由Linkerd自动将服务流量路由(甚至部分转移)至集群C。无论这些通信是发生在同一集群之内、跨越同一数据中心或VPC内的多个集群,抑或是跨越公共互联网,Linkerd都能在集群之间建立连接,并通过mTLS在两端完成加密与身份验证。 这项新的多集群功能可为Linkerd解锁大量用例,包括故障转移(在出现故障时跨越数据中心或云转移流量);“反向多租户”(每个租户都拥有自己的集群);混合云(工作负载可在本地环境与云环境之间往来移动,且不影响应用程序的其余部分)等等。 最后,与Linkerd的其他功能一样,多集群“服务镜像”方案能够充分利用现有Kubernetes功能,尽可能减少额外组件的介入。远程服务将被直接表示为Kubernetes服务,不引入任何新的CRD,且配置复杂度也将继续保持在最低水平。 2Ambassador支持多集群方案 这里我们还要向大家宣布,Ambassador项目的开发团队已经创建出多集群集成,允许用户们使用Ambassador部署作为Linkerd的多集群网关!感兴趣的朋友可以访问Ambassador项目博客以了解更多详细信息[1]。 3插件 2.8版本引入一套简单的add-on插件系统,用于从Linkerd处添加(或移除)各类功能。Linkerd 2.8自带两款插件: ◾Jaeger插件,用于添加Jaeger与oc-collector组件,旨在收集并显示对集群的分布式跟踪结果。 ◾Grafana插件(默认启用),用于向Linkerd仪表板添加Grafana图。 未来,我们将不断把更多功能以插件的形式推出。例如,您可以删除默认的Prometheus安装,转而使用您自己指定的其他工具。 4还有更多 Linkerd 2.8还带来诸多其他改进、性能增强与bug修复,具体包括: ◾通过新的Prometheus配置选项,Helm图表的灵活性与模块化水平都将得到提升。 ◾代理现在使用pod元数据对发出的分布式跟踪范围进行标记。 ◾对代理做出多项性能改进,旨在减少争用、改善延迟并减少伪超时。 ◾自动预防常见的流量循环场景。 关于更多详细信息,请参阅完整的发行版说明[2]。 5Linkerd项目后续发展路线图 我们坚信,Linkerd的核心价值正是其连通性——在云原生世界中,这种连通性不仅意味着“A与B可以交换数据包”,而更多体现为“A与B可以相互验证对方身份并交换数据包”。换句话说,其中包含着清晰的授权语义、可对第三方保密,且整个流程完全可测量、可检查。 展望未来,我们相信Linkerd能够成就这种连通性,并将其转化为适用于Kubernetes使用场景的安全平面。2.8版本的推出,标志着Linkerd又朝着这个方向迈进了一大步。在接下来的几个版本中,我们将继续充实Linkerd功能集,包括将mTLS扩展至所有连接、引入新的策略等等。我们仍在努力,大家敬请期待! 6立即使用! 准备好尝试Linkerd了吗?我们在每周实验版本[3]发布中已经向一部分用户朋友放出了最新版本。当然,大家也可以运行以下命令获取稳定的2.8版本: 1 curl https://run.linkerd.io/install | sh

June 22, 2020 · 1 min · jiezi

StatefulSet认识headless-service的作用sts

参考文章 Kubernetes 通过statefulset部署redis cluster集群 statefulset+NFS存储部署redis-cluster集群示例官方文档 Headless Serviceskubernetes之StatefulSet详解 为什么需要 headless service 无头服务?为什么需要volumeClaimTemplate?ss的几个重点: Pod管理策略, 更新策略.20200620更新 今天终于想到 headlesss service 有什么用了... 像 elasticsearch, etcd 这种分布式服务, 在集群初期 setup 时, 配置文件中就要写上集群中所有节点的IP(或是域名). 比如 es node.name: es-01network.host: 0.0.0.0## 对客户端提供服务的端口http.port: 9200## 集群内与其他节点交互的端口transport.tcp.port: 9300## 这里的数组成员为各节点的 node.name 值.cluster.initial_master_nodes: - es-01 - es-02 - es-03## 配置该节点会与哪些候选地址进行通信.discovery.seed_hosts: - 192.168.80.1:9300 - 192.168.80.2:9300 - 192.168.80.3:9300再像etcd listen-peer-urls: https://172.16.43.101:2380initial-advertise-peer-urls: https://172.16.43.101:2380initial-cluster: k8s-master-43-101=https://172.16.43.101:2380,k8s-master-43-102=https://172.16.43.102:2380,k8s-master-43-103=https://172.16.43.103:2380但是由于kuber集群的特性, Pod 是没有固定IP的, 所以配置文件里不能写IP. 但是用 Service 也不合适, 因为 Service 作为 Pod 前置的 LB, 一般是为一组后端 Pod 提供访问入口的, 而且 Service 的selector也没有办法区别同一组 Pod, 没有办法为每个 Pod 创建单独的 Serivce. ...

June 22, 2020 · 1 min · jiezi

利用Operator技术打包Helm图表并部署到K8S集群中

前言在“使用helm将复杂应用打包并部署到k8s集群中”这篇文章中我们用helm将应用打包为图表,而后通过其简化了部署流程,然而,helm对于基础安装(Basic Install)在行,虽支持无状态应用的无缝升级(Seamless Upgrades):替换镜像版本以利用K8S RC控制器的滚动升级特性,但其对于有状态应用却无能为力。 如若升级MySQL数据库,其是有状态的,故没法简单的替换程序版本来完成数据库升级,需执行一系列复杂的操作:使用mysqldump导出导入到新版本数据库,或采用原地升级方式执行脚本以更新数据库字典信息,这些复杂的逻辑对于helm来说无能为力,鉴于此,我们可将复杂的逻辑操作包装到operator中。 Operator提供了如上5个维度能力,其提供了”第一天“应用安装能力,也支持”第二天“应用升级维护、备份等全生命周期、深度分析、自巡航等特性。利用operator-sdk我们可将helm图表制成operator,使用ansible制作operator,亦或者用go语言开发operator。 为Helm图表创建Operator当将helm图表制作为operator后,其并没有具备超出helm图表的能力,换言之,若helm图表支持基础安装与无缝升级,那么制作成operator后不会多出备份~~~~等全生命周期等特性,但operator具有一些额外的能力。 首先安装SDK客户端,可参考文档Install the Operator SDK CLI。 $ RELEASE_VERSION=v0.18.1$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu && \ sudo mkdir -p /usr/local/bin/ && \ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu \ /usr/local/bin/operator-sdk && \ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu$ operator-sdk versionoperator-sdk version: "v0.18.1"若读者按照“使用helm将复杂应用打包并部署到k8s集群中”这篇文章配置并创建了helm图表与仓库,则执行如下命令对图表hello创建operator: $ operator-sdk new hello-operator \ --api-version=charts.helm.k8s.io/v1alpha1 \ --kind=Hello --type=helm \ --helm-chart-repo=http://chartmuseum.app.zyl.io \ --helm-chart=hello否则可将图表克隆到本地,而后执行operator-sdk new命令以基于本地目录创建operator,如下所示。 $ git clone https://github.com/zylpsrs/helm-example.git$ operator-sdk new hello-operator \ --api-version=charts.helm.k8s.io/v1alpha1 \ --kind=Hello --type=helm \ --helm-chart=helm-example/helm/hello上述命令生成了hello-operator目录,其结构如下所示: ...

June 20, 2020 · 3 min · jiezi

Kubernetes如何高效管理节点的资源

kubelet是Kubernetes中的主要节点组件,它执行许多关键任务。Kubelet主要职责在: 向kube-apiserver注册节点watch kube-apiserver中已经调度完成的Pod,并在Pod被调度完成之后告诉容器运行时(例如Docker)启动容器监视运行中的容器并将其状态报告给kube-apiserver执行活动性探针并在容器失败后重新启动容器运行由kubelet直接管理的静态Pod与Core Metrics Pipeline和容器运行时进行交互以收集容器和节点metrcis我们在本文中要讨论的另一个重要的kubelet任务是,当节点资源耗尽时,“agent”具有将Pods逐出的功能。当计算资源(例如磁盘,RAM或CPU)不足时,kubelet在维护节点稳定性方面起着至关重要的作用。对于Kubernetes管理员来说,了解配置资源超过配额的最佳做法很有用,以使节点资源更灵活,同时保留系统的整体容错性和关键系统进程的稳定性。 Kubelet如何确定资源不足?如前所述,kubelet可以从节点上驱逐工作负载,以释放资源来处理其他Pod和/或系统任务,例如容器运行时或kubelet本身。但是,kubelet如何确定资源不足? Kubelet根据收回信号和收回阈值确定何时回收资源。驱逐信号是系统资源(如内存或存储器)的当前容量。反过来,驱逐阈值是kubelet应该维护的此资源的最小值。 换句话说,每个驱逐信号都与某个驱逐阈值相关联,该阈值告诉kubelet何时开始回收资源。目前,支持以下驱逐信号: memory.available — 描述集群内存状态的信号。内存的默认逐出阈值为100Mi。换句话说,当内存下降到100 Mi时,kubelet开始驱逐Pod。nodefs.available — nodefs是kubelet用于卷,守护程序日志等的文件系统。默认情况下,如果nodefs.available <10%,则kubelet开始回收节点资源。nodefs.inodesFree — 描述nodefs索引节点内存状态的信号。默认情况下,如果nodefs.inodesFree <5%,则kubelet将开始驱逐工作负载。imagefs.available — imagefs文件系统是容器运行时使用的可选文件系统,用于存储容器镜像和容器可写层。默认情况下,如果imagefs.available <15%,则kubelet开始驱逐工作负载。imagefs.inodesFree — imagefs索引节点内存的状态。它没有默认驱逐阈值。上述驱逐阈值是非常合理的默认值。但是,用户可以通过在kubelet二进制文件上设置适当的标志来配置其自定义逐出阈值。这些用户定义的阈值可以更改默认的kubelet驱逐行为。 目前,Kubernetes支持硬驱和软驱逐阈值。 如果达到硬驱逐阈值,则kubelet将立即开始回收资源,而没有任何宽限期。相反,软驱逐阈值包括用户定义的宽限期,该宽限期应在kubelet开始回收任何资源之前到期。 您可以使用kubelet二进制文件上的--eviction-hard标志定义硬驱逐阈值。例如,kubelet-eviction-hard = memory.available <1Gi将告诉kubelet在节点的memory.available低于1Gi时开始回收资源。 如果要在驱逐之前允许宽限期,则可以将-eviction-soft标志与--eviction-soft-grace-period标志结合使用。例如,kubelet —- eviction-soft=memory.available<2Gi和kubelet —- eviction-soft-grace-period=1m30s将使驱逐阈值保持90秒,然后触发驱逐阈值。 用户还可以通过以秒为单位设置--eviction-max-pod-grace-period来指定允许的最大宽限期。 Kubelet如何回收资源?Kubelet以用户Pod的利益为代价来回收资源。它首先尝试回收未使用的容器镜像或 dead 的Pod。 如果节点具有专用的imagefs文件系统以及nodefs文件系统,则kubelet会以不同的方式回收节点资源。在这种情况下,如果nodefs达到驱逐阈值,则kubelet会删除所有已失效的Pod及其容器。相应地,如果imagefs达到驱逐阈值,则kubelet会删除所有未使用的容器镜像。 如果没有使用imagefs,则kubelet首先删除所有无效的Pod及其容器,然后删除所有未使用的镜像。有关此过程的更多信息,请参见Kubernetes文档。 如果回收容器镜像,失效的Pod和其他资源没有导致资源匮乏,则kubelet将删除用户Pod作为最后的选择。 kubelet根据Pod的QoS等级,Pod优先级和下面讨论的许多其他参数,决定退出哪个用户Pod。在描述此过程之前,让我们回顾一下Kubernetes中的基本QoS类。 Pod的Qos共分为Guaranteed,Burstable或Best-Effort。 Guaranteed : 在Pod的所有容器中都为CPU和RAM设置资源限制和请求,并且它们的值相等。Burstable Pod中一个或多个容器的资源(例如,CPU,RAM)设置了请求和限制的容器,它们不相等。Best-Effort Pod中的容器未设置资源限制。此QoS模型由kubelet在其Pod排序方案中隐式使用。通常,kubelet使用以下规则对驱逐候选人进行排名: Pod是否超出其资源请求。在Kubernetes中,Pod是根据其请求而不是限制进行调度的。因此,保证所有容器和Pod都具有它们所请求的RAM / CPU数量。但是,如果没有设置限制,并且Pod超出了其资源请求,则在保证Pod或某些系统任务需要受限资源的情况下,可以终止或限制该Pod。在某些情况下,甚至那些消耗少于要求量的Pod也会被杀死。例如,当系统任务内存严重不足并且没有较低优先级的Pod被杀死时。按Pod优先级排列。如果没有Pod超出其请求,则kubelet会检查Pod Priority。它将尝试先驱逐优先级较低的Pod。注意:在Kubernetes 1.14中,Pod的优先级和抢占式迁移到了GA。从1.11开始默认启用它们。您可以在本文中了解有关Pod Priority的更多信息。根据这些规则,kubelet会按以下顺序驱逐用户Pod: 驱逐的第一个候选对象是Best-Effort 和/或 Burstable的Pod,其受限资源的使用超出了请求。如果有多个此类Pod,则kubelet会按优先级对它们进行排序,然后将资源消耗按指定的请求进行排序。最后驱逐了资源使用量低于请求的Guaranteed 和 Burstable Pods的Pod。但是,如果某些系统任务(如kubelet或Docker)需要更大的资源,并且节点上没有Best-EffortPod,则kubelet可以驱逐消耗量低于其请求量的Guaranteed Pod。在这种情况下,它将首先以最低优先级驱逐Guaranteed 和 Burstable Pods。最低驱逐收回如果kubelet回收的资源量很小,则系统可以反复达到驱逐阈值。这不是理想的行为,因为它可能导致不良的调度决策和Pods频繁驱逐。为了避免这种情况,用户可以使用kubelet二进制文件上的-eviction-minimum-reclaim标志设置每个资源的最小回收级别。 例如,查看下面的kubelet配置: ...

June 18, 2020 · 1 min · jiezi

为Kubernetes证书续命

Kubernetes证书续命命令执行后,注意: 无论证书的到期时间如何,都会无条件地续订一年。证书的SAN等信息基于原证书,无需再次提供。renew执行后,为使更改生效,需要重启控制平面组件。kubeadm alpha certs命令仅支持v1.15及其以上的版本。命令如下: # kubeadm  alpha certs renew allcertificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewedcertificate for serving the Kubernetes API renewedcertificate the apiserver uses to access etcd renewedcertificate for the API server to connect to kubelet renewedcertificate embedded in the kubeconfig file for the controller manager to use renewedcertificate for liveness probes to healtcheck etcd renewedcertificate for etcd nodes to communicate with each other renewedcertificate for serving etcd renewedcertificate for the front proxy client renewedcertificate embedded in the kubeconfig file for the scheduler manager to use renewed# kubeadm alpha certs check-expirationCERTIFICATE                                  EXPIRES                      RESIDUAL TIME   EXTERNALLY MANAGEDadmin.conf                             Oct 24, 2020 05:25 UTC   364d            no      apiserver                                Oct 24, 2020 05:25 UTC   364d            no      apiserver-etcd-client             Oct 24, 2020 05:25 UTC   364d            no      apiserver-kubelet-client        Oct 24, 2020 05:25 UTC   364d            no      controller-manager.conf       Oct 24, 2020 05:25 UTC   364d            no      etcd-healthcheck-client        Oct 24, 2020 05:25 UTC   364d            no      etcd-peer                              Oct 24, 2020 05:25 UTC   364d            no      etcd-server                           Oct 24, 2020 05:25 UTC   364d            no      front-proxy-client                 Oct 24, 2020 05:25 UTC   364d            no      scheduler.conf                      Oct 24, 2020 05:25 UTC   364d            no

June 17, 2020 · 2 min · jiezi

Kubernetes防火墙配置

!!!先启动firewalld.service再启动docker.serivce 已经启动docker.service的启动firewalld.service后重启docker.service Master:不限制网段#!/bin/shfirewall-cmd --permanent --add-port=30000-32767/tcpfirewall-cmd --permanent --add-port=65535/tcpfirewall-cmd --permanent --add-port=8472/udpfirewall-cmd --permanent --add-port=68/udpfirewall-cmd --permanent --add-port=8118/tcpfirewall-cmd --permanent --add-port=6443/tcpfirewall-cmd --permanent --add-port=10200-10300/tcpfirewall-cmd --permanent --add-port=2370-2390/tcpfirewall-cmd --permanent --add-port=323/udpfirewall-cmd --permanent --add-port=443/tcpfirewall-cmd --permanent --add-port=4443/tcpfirewall-cmd --permanent --add-port=25/tcpfirewall-cmd --permanent --add-port=53/udpfirewall-cmd --permanent --add-port=80/tcpfirewall-cmd --permanent --add-port=9100/udpfirewall-cmd --permanent --add-port=9090/udpfirewall-cmd --permanent --zone=trusted --change-interface=docker0firewall-cmd --permanent --zone=trusted --change-interface=cni0firewall-cmd  --reloadfirewall-cmd --list-allMaster:限制网段#!/bin/shfirewall-cmd --permanent --add-port=30000-32767/tcpfirewall-cmd --permanent --add-port=65535/tcpfirewall-cmd --permanent --add-port=68/udpfirewall-cmd --permanent --add-port=8118/tcpfirewall-cmd --permanent --add-port=80/tcpfirewall-cmd --permanent --zone=trusted --change-interface=docker0firewall-cmd --permanent --zone=trusted --change-interface=cni0firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="25" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="6443" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="2370-2390" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="10240-10260" accept"firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="4443" accept"firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="443" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="53" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="8472" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="323" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="123" accept"firewall-cmd  --reloadfirewall-cmd --list-allNodes:限制网段#!/bin/shfirewall-cmd --permanent --add-port=30000-32767/tcpfirewall-cmd --permanent --add-port=65535/tcpfirewall-cmd --permanent --add-port=68/udpfirewall-cmd --permanent --add-port=8118/tcpfirewall-cmd --permanent --add-port=80/tcpfirewall-cmd --permanent --change-interface=docker0firewall-cmd --permanent --change-interface=cni0firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="25" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="2370-2390" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="tcp" port="10240-10260" accept"firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="4443" accept"firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="443" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="53" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="8472" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="323" accept"firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.40.0/24" port protocol="udp" port="123" accept"firewall-cmd --reloadfirewall-cmd --list-all

June 17, 2020 · 2 min · jiezi

当我们谈论云原生网络时究竟在谈论什么上

大家好!今天很高兴能有机会在这里跟各位分享灵雀云在云原生网络方面的实践和我们的思考。随着容器、Kubernetes、微服务等理念、技术的普及,云原生大幕开启。与此相应地,无论是平台的分布式化,还是业务的微服务化,都需要一个强大的网络来支撑虚拟节点和微服务之间的通信。 首先来看CNCF下面的这张图,CNCF对于网络架构的定义,可以看到Runtime这一层又可以分为资源管理、云原生网络、云原生存储。 1什么是云原生网络 云原生网络和传统网络的区别,可以从容器网络和物理网络之间的对比来看。一个直观的感受就是,容器网络的变化频率非常高。对物理网络来说,当机器上架,交换机路由器接好,所有物理机接到交换机之后,整体的网络拓扑就不会变了,后面的增删改查不会很频繁。 对于容器网络来说,在整个集群node、pod、工作负载、节点的数量变化都很频繁,每个容器的生命周期很短暂,导致网络的整体变化比传统网络高很多。同时,网络策略的变化也很频繁,对网络自动化有很高的要求。想象一下,生成容器如果需要人工进行网络配置,就无法发挥出云原生的价值。 此外,容器网络对网络自愈能力也有很高的要求,在如此变化频繁的情况下,单一硬件很难解决,会有很多软件,包括软件的可靠性、应用可靠性都会对网络产生干扰。如果网络节点的上线、下线,任何容器的启停、节点的故障调整都需要人去参与、恢复,对整体网络产生很大的影响,对网络自愈能力要求特别高。 但是,容器网络并不完全等于云原生网络。我们可以想象云原生最初的思路,它是为了跨平台的,云原生的应用不应该依赖于底层的基础设施;网络最好是跨各种环境的,公有云、私有云、物理机,可以随时在不同的云上进行迁移。如果你的网络是跟底层的某些具体实现绑定的,比如某个公有云或私有云,在跨平台方面的能力就会弱很多。在我来看,一个云原生的网络,是跟平台无关的,可以方便地跨云进行迁移。 容器网络的基本要求,首先每个pod需要单独IP,其次所有pod之间的网络三层直接可达,不经过任何NAT设备。也就是说,从这个pod直接访问另一pod看到的目标IP应该是同一个IP。第三,网络还需要提供一系列的网络应用,比如Service、DNS、NetworkPolicy、Ingress等。这些网络应用加上之前的容器网络,以及跨平台的特性,才构成了完整的云原生网络。 2云原生网络的开源实现 关于开源实现,CNCF很早就定义了一个标准——CNI(container network interface),它实际是一个可插拔式的容器网络协议,Flannel、Clillium、Calico等都是基于CNI协议来做的。它规定了上层调度系统和底层容器网络之间的一个交互协议,交互协议定义了两个接口:ADD和DEL。 我们从控制平面和数据平面两个角度对网络插件实现进行分类。控制平面是指网络之间是如何相互发现的,容器网络相当于在物理机器的网络上面又加了一层网络,那么网络之间是如何相互学习了解的?一个节点的容器是如何发现另一节点的容器?其中的机制是怎样的? 这种实现机制大致可以分为四类:一种是所有控制信息用分布式kv进行存储,典型如Flannel、Cillium,把所有的控制信息存到etcd,然后下发到每个节点。灵雀云开源的Kube-OVN是把所有的控制信息存到OVS DB,也是一个raft协议的分布式存储。 第二种是不通过物理层面的存储,直接通过现有网络层面的路由器或者交换机上的自我发现能力,比如Calico, Kube-Router通过路由协议,有一个协议的Agent,把路由信息发布到外部路由器和交换机,外部硬件的信息就可以通过路由协议把整个控制平台的信息进行转发。 第三种是用底层物理设备,物理机的控制平面就是交换机,相当于每个机器把网络接到交换机上之后,交换机就学到了如何进行控制平面的转发。如果容器能够直接接入底层物理设备的话,可以试试这种做法,比较典型的是Macvlan,IPvlan。 还有一种比较少见但挺有意思的实现方式,Gossip协议Weave,也叫八卦协议或者流行病协议。就是一个人告诉另一个人,另外一个人再去不断告诉其他人。 从数据平面角度来看,主要分为两种:一种封装模式,比如Flannel Vxlan, Kube-OVN Geneve, CalicoIPIP, Cillium Vxlan,以及跟封装模式相对的Underlay 模式: Flannel hostGateway, Kube-OVNVlan, Calico BGP 。 3云原生网络面临的挑战 云原生网络在实际落地时,也面临着一些挑战,主要分为四个方面。 第一,功能层面来看,云原生网络功能方面的能力比较少,落地时会碰到很多客户要做的新功能。 比如固定IP,当用户提出要求,只能要么网络这边改,要么应用方面改。多租户的能力,有的用户有很大的集群,有很多项目组,希望有租户管理的功能。租户不仅指计算资源的隔离,也包括网络资源的隔离。比如地址空间相对独立,网络控制独立,一些银行或其他金融机构希望流量经过交换机时是加密的,还有一些客户并非所有业务都上了K8s,这些应用需要相互之间进行交互,集群内外的网络互通也是一个问题。 第二,监控和故障排查,这是比功能层面更让人头疼的问题,上了容器网络后会发现大部分时间都是在运维这个网络,检查各种各样的网络问题。这其中最典型的可能就是网络不通。而且,如果涉及开发环境,微服务也可能一块上了,就会导致网络结构和拓扑变得特别复杂。 还有一个网络容易出现的问题--与已有技术栈的兼容。有些客户还有传统的网络监控方式,传统的网络监控已经很成熟了,但在容器网络这块是空缺的,会导致整体监控是缺失的,整体的排查经验也是缺失的,网络一旦出现问题,就会是很难解决的问题。 第三,安全性。传统方式可能采用基于黑白名单,或者基于IP划分的网络策略,但是容器在K8s上面,如果是用Networkpolicy,很多方式和传统是不一致的,会带来很多兼容性的问题。传统的流量审计流量回放会收集经过集群的所有流量,这种形式如果没有好的底层基础设施,很多安全机制相当于被架空了,这些都是落地时会碰到的问题。 第四,性能,提到性能大多数人会关注数据平面的性能。但在我们来看,现阶段比较大的问题是,用户的网络究竟能撑多大规模的集群,什么时候控制平面的性能会出现明显的衰减,这是在选型时需着重考虑的。数据平面的性能到实际应用时,很多情况下没有那么突出。它需要根据应用所需要的性能进行评估,很多情况下最大的极端的性能反而不是最需要的性能。

June 17, 2020 · 1 min · jiezi

小伙Kubernetes-部署如此简单你看完全明白了

将项目迁移到k8s平台是怎样实现的? 制作镜像控制器管理PodPod数据持久化暴露应用对外发布应用日志/监控 1、制作镜像分为三步第一基础镜像,是基于哪个操作系统,比如Centos7或者其他的第二步中间件镜像,比如服务镜像,跑的像nginx服务,tomcat服务第三步项目镜像,它是服务镜像之上的,将你的项目打包进去,那么这个项目就能在你这个服务镜像里面运行了一般运维人员都是提前将镜像做好,而开发人员就能直接拿这个镜像去用,这个镜像一定要符合现在环境部署的环境。 2、控制器管理 pod也就是k8s去部署这个镜像了,一般我们都会去拿控制器去部署,用的最多的就是 deployment Deployment:无状态部署StatefulSet:有状态部署DaemonSet:守护进程部署Job & CronJob:批处理无状态和有状态的有什么区别? 有状态的是有身份的,比如网络ID、存储、这个两个是提前规划好的,有序启动/停止 持久化与非持久化 3、Pod 数据持久化pod数据持久化主要是因对一个应用程序说的,比如开发一个项目,这个项目有没有落地到本地文件,如果有落的话,就保证他持久的有了,那就必须要用到pod数据的持久化了。 容器部署过程中一般有以下三种数据: 启动时需要的初始数据,可以是配置文件启动过程中产生的临时数据,该临时数据需要多个容器间共享启动过程中产生的持久化数据4、暴露应用在 k8s中,部署一个deployment,它是无法对外进行访问的,即其他应用程序要想访问部署的deployment,它找不到该怎么去访问。为什么去这么讲,因为deployment一般都是多副本的去部署,有可能会分布在不同的节点之上,而且重建 pod ip也会变,重新发布一下也会变了,所以没有办法去固定去访问哪个pod,即使固定了,其他的pod也访问不了。 要想做到多个 pod 都去提供服务的话,前面有必须要加一个负载均衡,提供一个访问入口,只有访问这个统一入口,才能转发到后端多个pod上,只要访问这个Cluster IP就能转发到后端的pod上。 Service Service 定义了 Pod 的逻辑集合和访问这个集合的策略Service 引入为了解决Pod的动态变化,提供服务发现和负载均衡使用 CoreDNS 解析 Service 名称5、对外发布应用 暴露出去之后呢,也就是需要让用户去访问,比如搭建一个电商网站,让用户去访问,ingress相对于service,它是一个互补的状态,弥补了各自,service主要提供了集群内部的访问,也可以暴露一个TCP/UDP的端口,而ingress主要是一个7层的转发,也就是提供一个统一的入口,只要访问ingress controller,它就能帮你转发你部署所有的项目,也就是所有的项目都使用域名去访问。 首先开发者将代码部署到你的代码仓库中,主流的用的Git或者gitlab,提交完代码通过CI/CD平台需要对代码进行拉取、编译、构建,产生一个War包,然后交给Ansible然后发送到云主机上/物理机,然后通过负载均衡将项目暴露出去,然后会有数据库,监控系统,日志系统来提供相关的服务。 首先也是开发将代码放在代码仓库,然后通过jenkins去完成拉取代码,编译,上传到我们的镜像仓库。 这里是将代码打包成一个镜像,而不是可以执行的war或者jar包,这个镜像包含了你的项目的运行环境和项目代码,这个镜像可以放在任何docker上去run起来,都可以去访问,首先得保证能够在docker上去部署起来,再部署到k8s上,打出来的镜像去放在镜像仓库中,来集中的去管理这些镜像。 因为每天会产生几十个或者上百个镜像,必须通过镜像仓库去管理,这里可能会去写一个脚本去连接k8smaster,而k8s会根据自己的部署去调度这些pod,然后通过ingress去发布我们的应用,让用户去访问,每个ingress会关联一组pod,而service会创建这组pod的负载均衡,通过service去区分这些节点上的Pod。 然后数据库是放在集群之外,监控系统日志系统也可以放在k8s集群放在去部署,也可以放在之外,我们是放在k8s集群内的,也不是特别敏感,主要用来运维和开发调试用的,不会影响到我们的业务,所以我们优先去k8s中去部署。 现在以部署一个JAVA项目到我们的k8s中 一、安装一个openjdk[root@k8s-master ~]# yum -y install java-1.8.0-openjdk.x86_64 maven[root@k8s-master ~]# java -versionopenjdk version "1.8.0_222"OpenJDK Runtime Environment (build 1.8.0_222-b10)OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)然后我们将代码拉到本地一般Dockerfile中跟我们的代码都放在同一目录下, ...

June 11, 2020 · 3 min · jiezi

简单5步轻松debug-K8S服务

在Kubernetes中,服务是一个核心概念。在本文中,将介绍如何调试K8S服务,这些服务是由多个Pod组成的工作负载的抽象接口(主机+端口)。 在我们深入探索debug方法之前,我们先简单回顾一下网络,这是Kubernetes服务的基础。 在一个pod中的容器共享相同的网络空间和IP。所有的pod都能通过IP彼此通信。每个节点都能看到所有的Pod,反之亦然。Pod可以看到所有的服务。那么,在实践中这些意味着什么呢? 在图中: 位于Pod1中的容器B可以直接作为localhost寻址容器A容器B可以通过其IP直接寻址Pod2(kubectl get pod -o wide)。我们知道当pod2出现故障时着不是一个可靠的通信渠道,并且一个新的pod可以出现在其位置中。但是我们无法追逐不断变化的目标。接下来,容器B可以通过Service x访问pod 2和pod 3,后者将它们的IP与负载均衡捆绑在一起;因此,在K8S上支持基于微服务的应用程序起着至关重要的作用尽管对Kubernetes的内部网络结构的检查不在本文的讨论范围内,但我稍后会发布一些参考资料以供大家进一步研究。 对于当下,我还是鼓励你花费一点时间在实践中经历和理解Kubernetes中的网络。例如,你可以启动一个Kubernetes测试pod并且尝试从该pod中访问其他pod、节点和服务。此处显示的命令将在Pod内弹出一个Linux shell。 kubectl run -it networktest --image=alpine bin/ash --restart=Never --rm现在你在Kubernetes网络空间内并且你可以随意使用wegt、ping、nslookup之类的命令进行实验。例如,测试你的Kubernetes集群中先前列出的网络要求,nslookup <servicename>, ping <PodIP>。 现在让我们回到我们的话题,troubleshooting Kubernetes服务,这实际上是一种网络结构。 Step1:检查服务是否存在kubectl get svc如果服务不存在,应该是服务创建出现了故障,因此要去检查你的服务定义。 Step2:测试你的服务请记住,一个内部的Kubernetes ClusterIP服务是无法在集群外部访问的。因此,有两种方法可以对其进行测试。方法一,你可以启动一个测试Pod,通过SSH进入该pod,然后尝试像这样访问你的服务: kubectl run -it testpod --image=alpine bin/ash --restart=Never --rm在本文中我们启动一个alpine Docker镜像作为pod来从其内部测试服务: #works for http serviceswget <servicename>:<httpport>#Confirm there is a DNS entry for the service!nslookup <servicename>或者,你可以转发到本地计算机并在本地进行测试。 kubectl port-forward <service_name> 8000:8080现在,你可以通过localhost:8000访问服务。 Step3:检查服务是否target相关PodKubernetes服务会根据标签selector将入站流量路由到其中一个pod,流量通过其IP路由到目标Pod。所以,请检查服务是否绑定到那些pod。 kubectl describe service <service-name> | grep Endpoints执行上述命令之后,你应该看到与列出的工作负载相关的所有Pod的IP。如果没有看到,请执行Step4。 ...

June 10, 2020 · 1 min · jiezi

Kubernetes三大落地姿势你pick谁

Kubernetes是面向企业的开源容器编排工具的事实标准,它提供了应用部署、扩展、容器管理等功能。经过几年的发展,Kubernetes已成为云计算和现代IT基础架构的通用平台,得到广泛应用进入产业落地期。 Kubernetes三种落地方式 当前企业客户落地Kubernetes实践主要有三种方式: ◾采用专业的容器厂商成熟的Kubernetes产品 Kubernetes本身是一个可扩展的平台,具有很好的灵活性,许多专业的容器厂商不满足于仅仅将Kubernetes作为容器编排工具来使用,而是将其定位为构建上层平台的核心框架。通过运用Kubernetes的扩展机制、架构模式与API规范,开发基于原生Kubernetes的产品体系。 这些专业技术厂商的Kubernetes产品功能完善、易用,经过CNCF官方一致性认证,以及客户实际生产环境的考验,并充分考虑了企业用户对安全性、稳定性的需求。能够根据使用场景提供企业就绪、开箱即用的完整解决方案,让开发者更关注业务本身,提高资源利用率。 ◾和专业容器厂商合作,共同打造容器云平台 国内许多大型企业都经历了多年信息化建设,内部有大量技术积淀。对这些企业用户来说,要完全摒弃当前的应用管理和部署方式是不现实的,循序渐进对原有应用进行容器化改造,探索企业自身的云原生迁移之路,不失为明智之举。 因此,企业会选择与专业容器厂商合作,通过联合开发来落地云原生技术,打造企业自身的技术中台。专业的技术厂商能够提供完善的咨询服务、解决方案和方法论,同时云原生技术的部署也一定程度上伴随着对企业IT文化、流程的变革,也需要技术厂商和企业的互相配合。 ◾基于社区版Kubernetes自建容器云平台 对于有一定技术能力的企业用户,会选择直接部署基于原生的、无任何侵入改动的社区版Kubernetes,在其之上构建应用。同时,与社区保持同步,根据新版本升级的频率更新自身的Kubernetes版本。 但是Kubernetes是一个全新而复杂的系统,企业自建Kubernetes并非易事,安装、部署和使用过程中会遇到各种困难和障碍,有较高的学习成本。作为一项系统性工程,落地Kubernetes还需要足够的集群、网络、存储等技术知识。尤其是Kubernetes运行在生产环境中时,其性能、可伸缩性、高可用性和安全性等方面所面临的挑战将更为严峻。 灵雀云企业级Kubernetes运维服务 针对基于Kubernetes社区版自建容器平台的企业用户,灵雀云企业级Kubernetes运维服务围绕Kubernetes全生命周期提供咨询、培训、技术支持与运维服务。灵雀云Kubernetes运维服务通过远程服务、现场支持和定期巡检等多种服务形式,让企业用户在享受K8s所带来的应用快速迭代、效率大幅提升红利的同时,降低采纳新技术导致的业务风险。 此外,灵雀云开源的Kubernetes网络组件Kube-OVN也将加入Kubernetes运维服务包。Kube-OVN是灵雀云开源的基于OVN的Kubernetes网络组件,通过将OpenStack领域成熟的网络功能平移到Kubernetes,来应对复杂的基础环境和应用合规性要求。针对Kube-OVN在部署和使用过程中遇到的技术问题,Kube-OVN核心作者团队将负责该网络工具全生命周期的技术支持和保障。 为什么选择灵雀云? 作为容器、Kubernetes领域的领先技术厂商,灵雀云已成为国内企业客户选择Kubernetes技术支持与运维服务的优选厂商。 ◾灵雀云是最早一批将Kubernetes产品化的专业服务商,产品全部基于原生Kubernetes架构; ◾灵雀云具有丰富的Kubernetes实践经验,Kubernetes技术和服务能力经过某部委、国家电网、中石油、各大股份制银行等众多大型客户实际生产环境的检验; ◾灵雀云拥有数十位有CKA和CKAD证书的Kubernetes技术专家,提供Kubernetes全生命周期服务方案,帮助企业应对棘手业务挑战; ◾灵雀云还拥有国内规模领先的专业服务交付团队,提供完善的培训、咨询、运维、巡检、故障排除等专业服务,并具备对服务的深刻理解。

June 9, 2020 · 1 min · jiezi

Kubernetes日志的6个最佳实践

本文转自Rancher Labs Kubernetes可以帮助管理部署在Pod中的上百个容器的生命周期。它是高度分布式的并且各个部分是动态的。一个已经实现的Kubernetes环境通常涉及带有集群和节点的几个系统,这些系统托管着几百个容器,而这些容器不断地基于工作负载启动、毁灭。 当在Kubernetes中处理大量的容器化应用和工作负载时,主动进行监控和调试错误十分重要。在容器、节点或集群级别,这些错误都能在容器中看到。Kubernetes的日志机制是一个十分重要的组件,可以用来管理和监控服务以及基础设施。在Kubernetes中,日志可以让你跟踪错误甚至可以调整托管应用程序的容器的性能。 配置stdout(标准输出)和stderr(标准错误)数据流 图片来源:kubernetes.io 第一步是理解日志是如何生成的。通过Kubernetes,日志会被发送到两个数据流——stdout和stderr。这些数据流将写入JSON文件,并且此过程由Kubernetes内部处理。你可以配置将哪个日志发送到哪个数据流中。而一个最佳实践的建议是将所有应用程序日志都发送到stdout并且所有错误日志都发送到stderr。 决定是否使用Sidecar模型Kubernetes建议使用sidecar容器来收集日志。在这一方法中,每个应用程序容器将有一个邻近的“streaming容器”,该容器将会将所有日志流传输到stdout和stderr。Sidecar模型可以帮助避免在节点级别公开日志,并且它可以让你控制容器级别的日志。 然而,这一模型的问题是它能够适用于小容量的日志记录,如果面对大规模的日志记录,可能会造成大量资源被占用。因此,你需要为每个正在运行的应用程序容器单独运行一个日志容器。在Kubernetes文档中,将sidecar模型形容为“几乎没有很大的开销”。需要由你决定是否尝试这一模型并在选择它之前查看它所消耗的资源类型。 替代方法是使用日志代理,该代理在节点级别收集日志。这样可以减少开销,并确保安全地处理日志。Fluentd已成为大规模聚合Kubernetes日志的最佳选择。它充当Kubernetes与你要使用Kubernetes日志的任意数量的端点之间的桥梁。你也可以选择像Rancher这样的Kubernetes管理平台,在应用商店已经集成了Fluentd,无需从头开始安装配置。 确定Fluentd可以更好地汇总和路由日志数据后,下一步就是确定如何存储和分析日志数据。 选择日志分析工具:EFK或专用日志记录传统上,对于以本地服务器为中心的系统,应用程序日志存储在系统中的日志文件中。这些文件可以在定义的位置看到,也可以移动到中央服务器。但是对于Kubernetes,所有日志都发送到磁盘上/var/log的JSON文件中。这种类型的日志聚合并不安全,因为节点中的Pod可以是临时的也可以是短暂的。删除Pod时,日志文件将丢失。如果你需要尝试对部分日志数据丢失进行故障排除时,这可能很难。 Kubernetes官方推荐使用两个选项:将所有日志发送到Elasticsearch,或使用你选择的第三方日志记录工具。同样,这里存在一个潜在的选择。采用Elasticsearch路线意味着你需要购买一个完整的堆栈,即EFK堆栈,包括Elasticsearch、Fluentd和Kibana。每个工具都有其自己的作用。如上所述,Fluentd可以聚合和路由日志。Elasticsearch是分析原始日志数据并提供可读输出的强大平台。Kibana是一种开源数据可视化工具,可以从你的日志数据创建漂亮的定制dashboard。这是一个完全开源的堆栈,是使用Kubernetes进行日志记录的强大解决方案。 尽管如此,有些事情仍然需要牢记。Elasticsearch除了由名为Elastic的组织构建和维护,还有庞大的开源社区开发人员为其做贡献。尽管经过大量的实践检验,它可以快速、强大地处理大规模数据查询,但在大规模操作时可能会出现一些问题。如果采用的是自我管理(Self-managed)的Elasticsearch,那么需要有人了解如何构建大规模平台。 替代方案是使用基于云的日志分析工具来存储和分析Kubernetes日志。诸如Sumo Logic和Splunk等工具都是很好的例子。其中一些工具利用Fluentd来将日志路由到他们平台,而另一些可能有它们自己的自定义日志代理,该代理位于Kubernetes中的节点级别。这些工具的设置十分简单,并且使用这些工具可以花费最少的时间从零搭建一个可以查看日志的dashboard。 使用RBAC控制对日志的访问在Kubernetes中身份验证机制使用的是基于角色访问控制(RBAC)以验证一个用户的访问和系统权限。根据用户是否具有特权(authorization.k8s.io/decision )并向用户授予原因(authorization.k8s.io/reason ),对在操作期间生成的审核日志进行注释。默认情况下,审核日志未激活。建议激活它以跟踪身份验证问题,并可以使用kubectl进行设置。 保持日志格式一致Kubernetes日志由Kubernetes架构中不同的部分生成。这些聚合的日志应该格式一致,以便诸如Fluentd或FluentBit的日志聚合工具更易于处理它们。例如,当配置stdout和stderr或使用Fluentd分配标签和元数据时,需要牢记这一点。这种结构化日志提供给Elasticsearch之后,可以减少日志分析期间的延迟。 在日志收集守护进程上设置资源限制由于生成了大量日志,因此很难在集群级别上管理日志。DaemonSet在Kubernetes中的使用方式与Linux类似。它在后台运行以执行特定任务。Fluentd和filebeat是Kubernetes支持的用于日志收集的两个守护程序。我们必须为每个守护程序设置资源限制,以便根据可用的系统资源来优化日志文件的收集。 结 论Kubernetes包含多个层和组件,因此对其进行良好地监控和跟踪能够让我们在面对故障时从容不迫。Kubernetes鼓励使用无缝集成的外部“Kubernetes原生”工具进行日志记录,从而使管理员更轻松地获取日志。文章中提到的实践对于拥有一个健壮的日志记录体系结构很重要,该体系结构在任何情况下都可以正常工作。它们以优化的方式消耗计算资源,并保持Kubernetes环境的安全性和高性能。

June 9, 2020 · 1 min · jiezi

BuildRun平台升级-支持Helm-v3兼容Helm-v2

Helm 是目前云原生技术体系中进行应用管理最被广泛使用的开源项目,可以帮助管理Kubernetes应用程序。通过Helm Charts,可以快速定义、安装和升级复杂的Kubernetes应用程序。 本文将简短介绍一下Helm v2与v3之间的区别,以及如何将BuildRun低代码开发平台的实例升级到helm v3上。 01 Helm v2和Helm v3的区别Helm设计之初不仅仅作为一个包管理工具,同时也试图作为一个微型的PaaS平台,因此添加了Tiller服务端,在Tiller服务端中有一整套管理流程和更新策略用以支持其作为PaaS平台的设定,但Tiller的存在却与Kubernetes概念产生了一些重合和冲突。 Tiller的存在导致release名称需要保持全局唯一性,故而不能像Kubernetes一样按照Namespace进行隔离。对于熟悉Kubernetes的用户来说,Tiller就显得有点多余,它的存在不仅提高了部署的复杂度,还含有一些安全隐患。 Helm v3在v2的基础上移除了tiller,变成了一个纯客户端工具,除此之外,还有如下一些变化: 部署实例依赖于用户在对应集群中所拥有的权限支持使用secret存储实例信息,更加安全实例按照namespace进行隔离,无需全局唯一移除requirements.yaml,直接在chart.yaml中定义依赖.... 02 升级Helm v3的必要性Helm v3相对于v2极大地提高了安全性,其部署权限完全依赖于终端用户所拥有的权限,而非tiller服务的权限,同时v3也更接近Kubernetes的设计理念,减少了开发人员的学习成本和不必要的疑惑。 03 BuildRun平台如何同时支持Helm v2和v3目前部分用户可能由于各种原因无法升级到Helm v3,所以BuildRun在升级Helm v3的同时保持了对v2版本的支持。 用户在激活集群时可以选择使用v2或者v3版本: 激活之后集群与平台交互流程如下: 如果用户部署v2版本,则helm-helper:v2会随之一起部署,如果用户部署v3版本则会一起部署helm-helper:v3,helm-helper:v2 与helm-helper:v3 为agent提供相同的接口,agent在进行helm操作时,可直接调用helm-helper接口,达到兼容v2和v3的目的。 04 如何从Helm v2升级到Helm v3Helm官方提供了升级插件,可以快速从Helm v2升级到Helm v3,BuildRun低代码开发平台上管理的集群可以参考以下步骤进行升级: ▍迁移v2版本的release到v3版本1. 下载Helm v3版本客户端,并安装2to3插件,安装插件命令如下: helm plugin install https://github.com/helm/helm-... 2. 执行迁移命令,其中helm_v2表示v2版本的Helm客户端,helm_v3表示v3版本的Helm客户端 helm_v2 list | grep -v NAME | awk '{print $1}' | xargs -n1 helm_v3 2to3 convert ▍停用旧版本Agent helm delete choerodon-cluster-agent-xxx --purge ...

June 8, 2020 · 1 min · jiezi

K8S-生态周报-几乎影响所有-k8s-集群的漏洞

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。Docker v19.03.11 发布距离 v19.03.10 发布仅一周时间,Docker 又发布了新版本 v19.03.11 。此版本是一个安全修复版本,通过禁用了 IPv6 路由地址广播(RA)从而防止地址欺骗,对应的漏洞为 CVE-2020-13401 。 在 Docker 的默认配置中,容器网络接口是指向主机(veth 接口)的虚拟以太网链接,在此配置下,如果一个攻击者可以在容器中以 root 身份运行进程的话,那么他是可以使用 CAP_NET_RAW 能力,向主机任意发送和接收数据包的。 例如: 在容器内使用 root 用户,可以正常执行 ping 命令 (MoeLove) ➜ ~ docker run --rm -it -u root redis:alpine sh/data # whoamiroot/data # ping -c 1 moelove.infoPING moelove.info (185.199.108.153): 56 data bytes64 bytes from 185.199.108.153: seq=0 ttl=49 time=54.389 ms--- moelove.info ping statistics ---1 packets transmitted, 1 packets received, 0% packet lossround-trip min/avg/max = 54.389/54.389/54.389 ms在容器内使用非 root 用户,执行 ping 命令会提示无权限 ...

June 8, 2020 · 2 min · jiezi

kubernetes-pod生命周期

在kubernetes集群中,pod的创建是一切的开始,本文介绍一下我所了解的pod的生命周期。k8s中kube-apiserver是对外提供访问的唯一借口,此组件提供了认证/授权/准入控制功能,其中准入控制包括了MutatingAdmissionWebhook和ValidatingAdmissionWebhook两种实现类型,其中istio等功能基于此实现,暂且不把准入控制计算到pod的生命周期中。 pod对象从其创建开始至其终止推出的时间范围成为生命周期。这其中包括创建主容器,初始化容器,容器启动后钩子,容器存活性探测,以及容器停止前钩子,其中其中主容器是必须的。 首先介绍一下pod生命周期的几种状态:Pending:创建pod的资源对象已经存入etcd但是pod尚未被调度。Running:pod已经被kubelet创建完成Secceeded:pod都已经终止成功并且不会被重启Failed:所有容器都已经终止,但是至少又一个容器终止失败,即容器返回了非0状态或已经被系统终止Unknown:api server无法正常获取到pod对象的状态信息。 pod创建的过程:1>用户通过API Server或其他API客户端提交pod Spec给API Server2>API Server将pod的信息存入到etcd中,待写入操作完成后,API Server返回确认信息至客户端3>API Server将信息写入到etcd中之后,其中informer机制开始起作用,通过watch机制将pod状态的变化反映到缓存中。(informer相关内容可以参考以下链接:https://www.jianshu.com/p/1e2...4>kube-scheduler的watch机制察觉到pod对象创建但是并未绑定到任何工作节点,kube-scheduler开始根据predicates以及priorities算法来计算pod的最佳运行节点,然后将pod的调度结果反映到API Server中(具体调度过程可以参考之前文章)。5>pod调度完成之后,由kubelet来创建pod并将容器状态返回至API Server存入到etcd中。6>写入成功之后并将结果反映到相应的kubelet。上面是创建pod的几个重要步骤: pod生命周期的几个重要行为: 1.初始化容器,初始化容器的两个特征:1)初始化容器必须运行完成才会创建主容器2)初始化容器按照定义的顺序串行运行 2.生命周期钩子:pod的生命周期钩子分为以下两种:1)postStart:容器创建完成之后执行的钩子处理程序,但是无法保证它一定会于容器中的endpoint之前运行2)preStop:容器终止之前立即运行的钩子处理器,它以同步的方式调用,完成之前阻止删除容器操作。 3.容器探测:容器探测分为就绪性探测和存活性探测1)就绪性探测:用于判断容器是否就绪并可对外提供服务2)存活性探测:用于探测容器是否处于运行状态,一旦处于非运行状态,杀死容器根据容器重启策略判断是否将其重启,为定义探测的默认状态是success上述两种探测支持三种处理方式:1)ExecAction:在容器中执行一个命令,根据命令返回状态码进行诊断2)TCPSocketAction:通过与容器的某个TCP端口尝试建立连接来判断将康状况3)HTTPAction:通过http调用的方式来判断健康状态上述健康检测涉及到pod的重启策略,pod中的几种重启策略:1)Always:pod对象终止就进行重启2)OnFailure:尽在pod出现错误时方才将其重启3)Never:从不重启 pod的终止过程:1)用户发送删除命令2)API 服务器中国内地饿破洞对象随着时间的推移而更新,在宽限期内(30秒)pod被视为“dead”3)将pod标记为“Terminating”状态4)与第三步同步,kubelet监听到pod对象转为“Terminating”状态的同时开启pod关闭过程5)与第三步同步,断点控制器(endpoint controller)监控到pod对象关闭时将其从所有匹配到此端点的server的端点列表中移除6)如果当前pod对象定义了preStop钩子处理器,则在标记为“Terminating”后开始同步执行,若宽限期结束,仍未执行完毕,则获得一个2秒的宽限期,继续执行7)pod对象中的容器进程收到TERM信号8)宽限期结束后,若存在任何一个仍在运行的线程,发送SIGKILL信号9)删除pod,对用户不可见默认情况下,都会又一个30秒的宽限期,不过可以在kubectl命令中使用--grace-period=<second>来定义时间长短,但此命令必须制定--force参数。 注:上述过程中很多地方用到了watch机制,涉及到client-go中的informer,建议查看以下该机制,参考链接:https://www.jianshu.com/p/1e2... 上面是就是创建pod的大致流程。

June 6, 2020 · 1 min · jiezi

为什么Kubernetes和容器与机器学习密不可分

当前,数字化转型的热潮在IT领域发展的如火如荼,越来越多的企业投身其中,机器学习和人工智能等现代技术的融合在公司组织内部也逐渐流行起来。 随着那些构成企业复杂IT基础架构的技术日益成熟,部署云原生环境以及在该环境中使用容器早已成为企业技术轨道中的“家常便饭”。 幸运的是,对于企业所有者而言,Kubernetes和容器部署技术不仅可以与机器学习技术并驾齐驱,而且可以引入到云原生模型中,从而为企业提供良多裨益,包括实施有效的业务策略以及安全性的培养。 当我们谈到机器学习时,你会想到什么?机器的应用场景是多种多样的 -- 从简单的欺诈/网络犯罪侦查,到量身定制的客户体验,再到像供应链优化这样复杂的操作,一切都证明了机器学习能够为企业所带来的丰厚利润。 此外,Gartner的预测进一步证明了机器学习所提供的众多优势,该预测指出,到2021年,70%的企业都将依赖于某种形式的人工智能。 人工智能在业务中的应用 企业若想充分利用人工智能和机器学习,并将其应用于DevOps和DevSecOps等新业务组中,他们必须拥有可靠的IT基础架构。 强大的IT环境能够为数据科学家提供尝试各种数据集、计算模型和算法的环境,而不会影响其他操作,也不会给IT人员造成损失。 为了在业务中有效实现机器学习,企业需要找到一种在本地和云环境中重复部署代码的方法,并建立与所有所需数据源的连接。 对于现代企业而言,时间是帮助他们实现目标的基本工具,因此,他们迫切需要一种支持快速开发代码的IT环境。 说到容器,容器通过将代码及其特定的运行要求打包在“包装”中,从而加快了企业应用程序的部署过程,这一特性使容器成为了企业的理想选择,也因此成为了机器学期和人工智能的理想搭档。 综上所述,基于容器环境下进行的人工智能项目的三个阶段,包括探索、训练模型和部署,是非常有潜力的。每个阶段具体又包括什么呢?下文将对这三个阶段展开说明。 01 探索在构建AI模型时,数据科学家们遵循的规范是尝试不同的数据集以及各种ML算法,以确定要使用的数据集和算法,以便他们可以提高预测水平效率和准确性。 通常,数据科学家依靠大量的库和框架来为不同行业中的各种情况和问题创建ML模型。当数据科学家们试图发现新的收入来源并努力实现企业的业务目标时,他们还需要具备运行测试并快速执行测试的能力。 尽管AI技术的使用日新月异,但已有数据表明,令数据科学家和工程师使用容器化开发的企业比其竞争者更据优势。 渥太华DevOps工程师Gary Stevens的一份报告指出,加拿大网络托管提供商HostPapa的表现优于其他领先的网络托管提供商,这要归功于它早早地采用了Kubernetes。 在AI或ML项目的探索阶段结合容器,能够使数据团队根据他们的特定领域,自由打包库;相应地部署算法,并根据团队需求明确正确的数据源。 随着基于容器的程序(例如Kubernetes)的成功实施,数据科学家有权访问隔离的环境。这使得他们可以自定义探索过程,而不必在共享环境中管理多个库和框架。 02 模型训练设计完模型后,数据科学家需要利用大量数据,跨平台训练AI程序,以最大程度地提高模型的准确性,并减少任何人工资源的使用。 考虑到训练AI模型是一项高度计算密集型操作的事情,容器被证明在扩展的工作负荷以及快速与其他节点通信方面非常有利。但是,通常情况下IT团队的成员或调度程序会确定最佳节点。 此外,通过容器进行现代数据管理平台进行数据训练,极大地影响并简化了AI模型中的数据管理流程。此外,数据科学家还具有在多种不同类型的硬件(例如GPU)上运行AI或ML项目的优势,这也使他们能够一直使用那些最具准确性的硬件平台。 03 部署作为AI项目中最棘手的部分,在机器学习应用程序的生产和部署阶段中可能经常会出现多个ML模型的组合,而每个模型都有其不同的用途。 通过在ML应用程序中结合容器,IT团队可以将每个特定模型部署为单独的微服务。那么,微服务又是什么?微服务是指一个独立的轻量级程序,开发人员能够在其他应用程序中重复使用该程序。 容器不仅为快速部署ML和AI模型提供了一个可移植的、隔离且一致的环境,也拥有可能改变当今IT格局的能力,那就是使企业能够更快更好地实现其目标。 原文链接:https://www.infosecurity-magazine.com/opinions/kubernetes-containers-machine/ 以上信息来源于网络,由“京东智联云开发者”公众号编辑整理,不代表京东智联云立场 欢迎点击“京东智联云”了解更多精彩内容!

June 6, 2020 · 1 min · jiezi

Vmware虚拟机网络配置

一,概念常见网络配置策略 NAT,网络地址转换,虚拟机和真实机的网卡在不同网段。BRIDGE,桥接,虚拟机和真实机在相同网段。当真实机切换网段,则导致虚拟机需要修改配置。 二,NAT配置要点 1、编辑=》虚拟网络编辑器 2、选择NAT模式=》修改子网ip和掩码:192.168.85.0和255.255.255.0 3、NAT设置=》修改网关:192.168.0.1 4、物理主机,网络和共享中心=》更改适配器=》VMNet8:与前3步一致 5、虚拟机,编辑网络配置文件/etc/sysconfig/network-scriptsIFCFG-ENS33 BOOTPROTO="static"IPADDR="192.168.85.125"NETMASK="255.255.255.0"GATEWAY="192.168.85.1" 6、重启网络配置:service network restart

June 5, 2020 · 1 min · jiezi

使用Istio和Spring-Boot在Kubernetes上进行熔断和重试

对于每个服务网格框架来说,处理服务间通信中的通信故障的能力是绝对必要的。它包括超时和HTTP错误代码的处理。在本文中,我将展示如何使用Istio配置重试和熔断机制。与之前Kubernetes上使用Istio Service Mesh的文章相同,我们将分析在Kubernetes上部署的两个简单Spring Boot应用程序之间的通信。但是,我们将讨论更高级的主题,而不是非常基本的示例。 示例为了演示Istio和Spring Boot的用法,我在GitHub上创建了带有两个示例应用程序的存储库:callme-service和caller-service。该存储库的地址为https://github.com/piomin/sample-istio-services.git。前言中已经提到与Istio有关服务网格的第一篇文章使用了相同的存储库。 架构我们的示例系统的体系结构与上一篇文章非常相似。但是,存在一些差异。我们不是在使用Istio组件注入故障或延迟,而是直接在源代码内部的应用程序上注入错误或延迟。为什么?现在,我们将能够直接按照为callme-service创建的规则进行处理,而不必像以前那样在客户端进行处理。另外,我们正在运行两个callme-service应用程序版本v2实例,以测试熔断器对相同服务(或相同Deployment)实例的作用如何。下图说明了当前描述的体系结构。 Spring Boot 应用我们从示例应用程序的实现开始。应用程序callme-service公开了两个端点,这些端点返回有关版本和实例ID的信息。端点GET /ping-with-random-error将HTTP 504错误代码设置为对约50%请求的响应。端点GET /ping-with-random-delay返回的响应具有0s和3s之间的随机延迟。这是callme-service端 @RestController的实现。 @RestController@RequestMapping("/callme")public class CallmeController { private static final Logger LOGGER = LoggerFactory.getLogger(CallmeController.class); private static final String INSTANCE_ID = UUID.randomUUID().toString(); private Random random = new Random(); @Autowired BuildProperties buildProperties; @Value("${VERSION}") private String version; @GetMapping("/ping-with-random-error") public ResponseEntity<String> pingWithRandomError() { int r = random.nextInt(100); if (r % 2 == 0) { LOGGER.info("Ping with random error: name={}, version={}, random={}, httpCode={}", buildProperties.getName(), version, r, HttpStatus.GATEWAY_TIMEOUT); return new ResponseEntity<>("Surprise " + INSTANCE_ID + " " + version, HttpStatus.GATEWAY_TIMEOUT); } else { LOGGER.info("Ping with random error: name={}, version={}, random={}, httpCode={}", buildProperties.getName(), version, r, HttpStatus.OK); return new ResponseEntity<>("I'm callme-service" + INSTANCE_ID + " " + version, HttpStatus.OK); } } @GetMapping("/ping-with-random-delay") public String pingWithRandomDelay() throws InterruptedException { int r = new Random().nextInt(3000); LOGGER.info("Ping with random delay: name={}, version={}, delay={}", buildProperties.getName(), version, r); Thread.sleep(r); return "I'm callme-service " + version; }}应用程序caller-service公开了两个GET端点。它使用RestTemplate来调用callme-service公开的相应GET端点。它还返回caller-service的版本,但是只有一个标有version = v1的应用程序的部署。 ...

June 5, 2020 · 3 min · jiezi

如何选出适合自己的管理Helm-Chart的最佳方式

本文转载自Rancher Labs 无论你喜欢与否,你都不得不承认Helm是管理Kubernetes应用程序独一无二的工具,你甚至可以通过不同的方式使用它。 在Helm的使用过程中,我们注意到有几个问题不断出现: 你将你的Helm chart放在哪里?你是使用app文件保存它们还是使用chart仓库? 你如何划分Helm chart?你是使用一个共享的chart或是为每个服务维护一个chart? 我正在通过我以往在各种创业公司的经验来尝试解决这些问题,但是我也借鉴了大型公司的做法。 以下是我要概述的几个方法: 使用一个chart仓库来存储一个大型共享chart使用一个chart仓库来存储许多特定于服务的chart使用特定于服务的chart,这些chart与服务本身存储在同一仓库中然后,我将介绍在决定这些选项时应该考虑的因素,例如依赖项差异和团队结构等。 Option1:在一个chart仓库中维护一个大型共享chart在我们一个项目中,我们从一个用于部署多个服务的大型chart开始。它存储在ChartMuseum中,并由负责部署基础架构的人员进行维护。 如果你的各个服务在本质上十分类似,那么共享chart可以为你省去很多麻烦。这里我们采用Helm维护者Josh Dolitsky在KubeCon 2019上描述的情况: 我最近在负责一个项目,这个项目包含9个微服务……我意识到它们几乎都是相同的HTTP监听服务。所以我决定仅仅构建一个helm chart来部署9个不同的服务,为每个服务做不同的配置——仅为特定的服务设置一个新的docker标签。 在这种情况下,将Helm chart存储在ChartMuseum等chart仓库中是有意义的,因为只有值需要保存在这些特定服务的仓库中。 Option2:在一个chart仓库中维护几个特定于服务的chart特定于服务的chart优势在于,你可以更改一项服务,而无需担心会破坏另一项服务。但是它们可能会导致重复的工作——如果你要更新通用配置,则必须在每个chart中进行相同的更改。 是否需要在一个chart仓库中保存它们则是另一个问题了。如果这些chart是特定于服务的,那么将它们存储在一起尚没有强有力的架构论证。当然,如果你有专门的人员或团队来维护所有的chart,一起存储多个特定于服务的chart通常会比较容易。 例如,与我一起工作的一位DevOps工程师,他在一个中心chart仓库中维护15种不同的微服务chart。对于他而言,在同一个位置更新所有chart比向15个不同的仓库提交拉取请求要容易得多。开发人员当然清楚如何更新chart,但是处理资源相关的设置显然更吸引他们。 Option3:在与服务本身相同的仓库种维护特定于服务的chart对于基于微服务的应用程序来说,特定于服务的chart是一个很好的选择。而当你将每个chart与服务代码保存在同一仓库中时,使用特定于服务的chart则会更好。 如果你在服务仓库中存储Helm chart,那么可以更轻松地独立于其他项目持续部署服务。并且你可以将chart更新(例如添加新变量)与应用程序逻辑的更改一起提交,使其更易于识别和还原重大更改。 然而,本选项的优势取决于你所维护的微服务的数量。如果你的微服务数量正迈入两位数,那么这一选项的优势则没有那么明显,更多的是阻碍。如果你要处理非常同质的服务(如Josh Dolisky),则尤其如此。 决定选项时需要考虑的因素一般情况下,有两个方面需要考虑: 依赖项和可重现:每个服务的依赖项有多少区别?对一个服务的更改有多大风险会中断另一个服务?你如何再现特定的开发条件?团队结构:你负责每个服务的小型自治团队吗?你有了解DevOps的开发人员吗?你的团队中DevOps文化流行程度如何?依赖项和可重现如果你将你的chart和应用程序分开维护,它们的版本将彼此不同。如果你在部署时遇到问题,并且需要重现导致该问题的条件,则需要确定:a)服务版本;b)用于部署它的chart版本。你可能想要走捷径,使用“latest” chart来测试服务x.x.x,但这并不是一个好想法,因为这样你将永远无法重现造成问题的确切条件。 那么,如果你经常需要更改的chart版本怎么办?是不是应该一起测试这些改动呢? 考虑到许多开发人员需要创建同一共享chart中的分支版本这一场景: 开发人员(图中的Edeltraud和Eberhardt)分别在不同的分支中工作,并且想要在开发环境中测试他们的更改以及图表更改——所以他们还需要分支chart。同时,DevOps工程师在他的共享chart的分支中更新一些常用组件。 如果没有人将他们的chart更改更新到各个分支,那么就有可能破坏另一个服务部署。 不久前,我们正好遇到了这个问题。Chart维护者用一个新的条件块更新了共享chart。该语句检查了一个新的变量“foo”是否被设置为“启用”。然而,变量“foo”还没有在所有服务的值文件中定义。对于缺少该变量的服务,部署中断了。不幸的是,当时chart中没有定义默认的回滚行为。 如果chart和代码位于同一个仓库中,并且可以在同一个分支中进行测试,则针对这些问题的测试将更加容易。 即使一开始似乎是矫枉过正,我们也会这样做。我们的工作对象是很少有依赖项的服务。对于每个服务,Helm chart只部署一个带有特定Docker标签的主容器。chart的名称和docker标签是通过变量传递进来的。尽管如此,我们仍然避免了使用共享chart,而是选择在每个服务仓库中放置单独的chart。 这主要是因为我们只处理了四个服务。但我们的开发人员也更喜欢掌控所有能够影响CI/CD的配置。然而情况并非总是如此,所以现在是研究另一个维度的好时机。 团队结构Chart维护的问题同时也取决于谁管理部署流程。 这里推荐另一篇文章,由Helm维护者Matt Farina撰写的,在文章中他阐述了关于Helm正在尝试解决复杂性的话题。文章链接: https://codeengineered.com/bl... 他阐明了必须处理Kubernetes复杂性的三个主要角色。为了清楚起见,我将对其内容进行一些解释,并将角色描述如下: App开发人员——这个角色主要构建服务、添加特性以及修复bugDeployer——这个角色负责将应用程序推向世界。理想情况下,有一个不错的自动化程序可以为他们部署应用程序,但是他们知道它的工作方式,可以根据需要进行修改。系统工程师——这一角色负责维护deployer部署的Kubernetes环境。他们是管理计算机资源的专家,并且可以尽量减少任何服务的停机时间。第一个和第三个角色你都能在公司里找到与其负责内容相符的职位,而Deployer这个角色则有些模糊,这个角色所负责的内容常常会被其他两个角色的人接管——这会影响你如何管理你的Helm chart。 尚在早期阶段的初创公司的DevOps如前所述,我们的业务是为初创企业提供运维支持,这些企业往往需要快速扩大规模。我们见过很多“非常规”的设置和分工。在早期阶段,App开发者可能会负责各种事情,有些人甚至会帮忙完成系统管理员的任务,比如设置打印机或配置办公室网络等。他们会尽力去了解其他两个角色所需要负责的内容,因为没有人可以帮助他们(直到我们参与进来)。 一旦他们想了解Helm,大多数应用开发者会把他们的chart放在最容易处理的地方——也就是他们维护的同一个repo。 在大型企业中的DevOps你可能在一个更大的、架构更分明的团队中工作, 在这种情况下,你可能有自己的DevOps工程师甚至是整个DevOps部门。而这个人或团队经常会觉得自己也要负责 “Deployer”的角色。很有可能,他们会倾向于采用更集中的方法,比如将所有的chart存储在ChartMuseum这样的chart仓库中。更不愿意让应用开发者过多地参与到Helm chart中来(往往是有合理缘由的)。 例如,我最近看了一个经典的技术讲座,叫《从头开始构建Helm chart》,由VMWare系统工程师Amy Chen主讲。在她的开场白中,她说: 在基础设施方面,你的主要目标是时刻准备着应对故障,没有信任——在这个意义上说,就像我不太愿意信任我的APP开发者,并且我也不太需要信任我的APP开发者。这是可以理解的。你不想让应用开发者去搞乱设置,比如CPU和内存限制,或者是pod中断预算。但整个 “DevOps文化”的概念是专门为了改善基础设施维护者和开发者之间有时会出现的疏离关系而演化出来的。 实践DveOps文化Atlassian(JIRA和Trello的所有者)出版了一本“团队手册”,其中定义了DevOps文化: DevOps文化是关于开发者和运维之间的共同理解,并为他们所构建的软件分担责任。这意味着增加透明度、沟通和协作,并在开发、IT/运维和 “业务”之间进行合作。如果将其实际应用到Helm chart维护和一般的基础架构配置中,就会把大部分的责任放在应用开发者的手中。他们也会承担起“Deployer”的角色,并改变他们拥有的仓库中的配置。 系统工程师仍然可以把他们专门维护的设置集中起来。例如,一些团队也会维护一个中央基础架构repo,该repo中保存着Terraform配置或Helm文件等常用资源,这些资源是启动新项目所需要的(例如,用于设置ingress controller和cert manager)。Helm 3还支持所谓的 “library chart”,它只能作为另一个chart的一部分进行部署。这让我们更容易区分常见的和服务特定的变更责任。 ...

June 3, 2020 · 1 min · jiezi

kubernetes-configmap热加载

在kubernetes中,configmap的用途用来传递参数给应用,主要的用法:1、使用configmap挂载env2、使用configmap挂载volume具体的yaml文件不写了,具体的可以搜索一下使用上述两种方法给应用传递参数之后,会有两种结果:第一种:使用env方式挂载的configmap,在configmap更改之后,再次去查看变量的值,此时,变量的值是没有改变的。第二种:使用volume的方式挂载configmap之后,当configmap更新之后,变量的值会发生变化,但是中间会存在一定的时间间隔,大约是10左右,这主要是因为kubelet 对pod的同步间隔是10秒,另外需要注意的是当使用subpath将configmap中的某个文件单独挂载到目录下,那这个文件是无法热更新的,这是configmap本身的逻辑决定的。 上述两种方式配置参数的方式可以根据自己的需要进行选择,如果对实时性没有要求可以使用volume进行挂载。当参数更新之后并不代表业务逻辑更新了,需要通知业务重新通知业务进行逻辑上的更新。 应用本身可能不存在热加载的逻辑,可能要考虑别的方式来对配置参数进行热加载:第一种:使用sidecar方式来对配置参数监听,然后根据各自应用本身业务的逻辑来对参数进行热架子啊第二种:不适用上述sidecar的方式,直接将主进程和sidecar进程打进同一个镜像中,然后进行热加载第三种:应用本身监听配置的变化,在逻辑中处理热加载或者是使用第三方封装好的库。 上述方式可能会存在这样那样的限制,换一种解决思路就是对应用进行滚动更新操作,当pod发生滚动更新时,配置参数肯定会重新进行加载,这样就可以保证配置参数更新了,滚动更新实现方式:可以在yaml文件中添加annotation,每次更新参数时,更新该注解,也可以在CI流程中实现(将configmap计算一个hash值,每次更新都会改变,然后触发滚动更新操作) 参考链接:https://aleiwu.com/post/confi...https://jimmysong.io/kubernet...

June 3, 2020 · 1 min · jiezi

kubernetes-容器调度

kubernetes调度的目的就是为pod寻找一个最合适的node。最合适node的挑选过程分为两步:1)从集群所有的节点中根据调度算法选出所有可运行该pod的节点2)从上一步的结果中,再根据调度算法挑选出一个最符合条件的节点运行pod 在调度过程中,默认调度器首先会调用一组叫做Predicates的调度算法选出一组合适的node,然后再运行Priority调度算法,来给通过Predicates算法选出的node进行打分,最终分数最高的那个节点即是pod运行的节点。 声明一个点:调度器对一个pod调度成功,实际上就是将它的spec.nodeName字段填上调度结果的node名字。调度原理示意图如下所示:上图中informer path启动一系列informer,用来监听etcd中的Pod、Node、Service等与调度相关的API对象,当一个pod被创建出来之后,就将这个pod添加到待调度队列(优先级队列)。 上面informer path将pod加入到待调度队列中,下面的scheduling path从调度队列中取出pod,通过Predicates调度算法,从cache中拿到node信息,选出pod可运行的node,然后再调用Priorities算法为选出的node进行打分,从0到10,得分最高者,就是pod最终运行的node。 上述挑选过程执行完成之后,将pod中的nodename设置为node的名字,这个步骤被称为Bind。 上述bind阶段只会更新cache中node和pod的信息。这种“乐观”假设的API对象的更新方式,在kubernetes里被称作Assume。 当assume完成之后,调度器才会创建一个Goroutine来异步的向APIServer发起更新请求,来完成真正的Bind操作。当调度器的“乐观”绑定之后,当pod在node上运行之后,该节点上的kubelet还会执行一次操作,确认该pod真正可以在该节点上运行。 上面描述了pod的调度过程,提到了Predicates调度算法和Priorities调度算法,下面是对Predicates调度算法的一些描述。Predicates可以看过是Filter,通过Filter选出当前pod可运行的node,是硬性条件。在kubernetes中,默认的调度策略有如下几种:第一种:GeneralPredicates;主要是对宿主机的CPU和内存资源以及其他各种基础条件进行检测。第二种:与volume相关的过滤规则;第三种:是宿主机相关的过滤规则。第四种:是pod相关的过滤规则。比如pod之间的亲和性和反亲和性。 上述是Predicates算法相关的过滤规则,执行完之后,再执行Priorities算法对选出的node进行优选。主要是通过一些算法对node进行打分,选出分数得分最高的node去运行pod。 上述是pod的大致调度流程,此外默认调度器还有优先级和抢占机制。首先优先级和抢占机制是解决pod调度失败的问题。当一个pod调度失败之后它会被暂时搁置起来,知道pod更新或者集群状态发生变化,调度器才会对这个pod重新进行调度。此时kubernetes有一个优先级的概念,当优先级高的pod调度失败之后该pod不会被搁置,而是会挤走某个node上优先级低的pod,这样保证高优先级pod被调度成功。这个机制在1.10之后才逐步可用。要使用这个机制,首先要在集群中提交一个PriorityClass: apiVersion: sceduling.k8s.io/v1beat1kind: PriorityClassmetadata: name: hige-priorityvalue: 1000000globalDefault: falsedescription: "This priority class should be used for high priority service pods only."上述指定了一个优先级为1000000的PriorityClass。在kubernetes中,优先级是一个32bit的整数,最大值不能超哥10亿,并且数字越大优先级越高,超出10亿部分作为保留部分被k8s自身使用。如果没有声明的话默认是0,可以通过以下命令在集群中查看: kubectl describe po redis-cluster-operator-7b987d6477-xdrhw | grep PriPriority: 0定义了优先级在声明pod时指定priorityClassName即可: spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent priorityClassName: high-priority上述是关于优先级的描述。当一个高优先级的pod调度失败的时候,调度器的抢占能力就会被触发。这时调度器从集群中寻找一个节点,使得当这个节点上的一个pod被删除,待调度的高优先级pod就可以被调度到这个节点上,这就是抢占。 抢占过程发生时,并不会立刻被调度到被强占的Node上,而是将抢占者的nominatedNodeName字段设置为被强占的Node的名字。然后强占者会重新进入下一个调度周期,然后在调度周期来决定是不是要运行在被强占的节点上。 调度器的抢占机制原理:调度器抢占算法的一个最重要的设计就是在调度队里,使用了两个不同的队列,第一个叫做ActiveQ,凡是在这个队列中的pod都是下一个调度周期需要调度的对象。第二个叫做unschedulableQ,专门用来存放调度失败的队列。当unschedulableQ中的pod被更新之后,调度器会自动把这个pod移动到activeQ中,从而给pod重新调度的机会。 在抢占者调度失败之后,抢占者被放倒unschedulableQ中,这时会触发会抢占者寻找失败者的流程:第一:调度器会检查这次失败事件的原因,来确认抢占是不是可以帮助抢占者找到一个新节点。第二:如果确定抢占可以发生,那么调度器就会把自己缓存的所有节点信息复制一份,然后使用这个副本来模拟抢占过程。检查副本中的每一个节点,确认该节点上的pod删除之后抢占者是否可以在这个节点上运行,一旦可以运行,记录下来,这就是抢占的过程。 当模拟抢占过程成功之后调度器就会开始真正的抢占操作:第一步:调度器会检查牺牲者列表,清理这些 Pod 所携带的 nominatedNodeName 字段。第二步:调度器会把抢占者的 nominatedNodeName,设置为被抢占的 Node 的名字第三部:调度器会开启一个 Goroutine,同步地删除牺牲者。 接下来调度器就通过正常的调度流程调度抢占者。 关于pod的优先级以及抢占调度在kubernetes1.11之后是beta版本,可以根据个人需要来决定是否开启。 以上整理自极客时间“深入剖析kubernetes” ...

June 3, 2020 · 1 min · jiezi

kubernetes-crd-operator

kubernetes crd operator 开发 声明:这篇文章主要是我个人开发crd过程中的相关学习以及总结,其中包括网上看到的已有成果和个人心得。 kubernetes相关crd概念不做过多介绍,这里主要介绍开发crd两个相关的framework,包括:operator-sdk和kubebuilder。 operator-sdk 官网:https://sdk.operatorframework... kubebuilder 官网:https://book.kubebuilder.io/q... 关于operator-sdk编写operator的例子,可以参考以下链接: https://zhuanlan.zhihu.com/p/... 链接当中已经包括了从安装,到创建一个简单的deployment以及service,链接的中例子应该有一个小小的失误,我已在评论中提出。注意,operator-sdk相关版本不一样可能会导致生成的东西有小小差异。关于operator-sdk的安装也可以参考官网,官网已经做了详细的描述,官网安装链接: https://sdk.operatorframework... 安装完毕之后,operator-sdk官网有两种不同开发方式:一种是基于ansible;一种是基于golang的,我选择的是基于golang的。基于golang的operator开发,官网已经给出了详细的步骤,不做过多描述。 接下来说一下我个人开发过程中遇到的一些点: 1)开发过程中,如果每次都部署到集群中去调试非常的浪费时间,可以在本地进行调试: 使用以下命令进行本地调试,注意:operator-sdk启动时默认是从本地.kube/config配置文件读取集群配置信息。项目启动命令: 1>首先要部署CRD文件 2>在项目目录下执行命令:operator-sdk run --local 通过上述两步即可启动项目,进行本地调试。 在开发过程中涉及到需要修改所定义类型的spec(即修改*_type.go文件),这是需要执行如下命令重新生成code: operator-sdk generate k8s 上述是使用operator-sdk开发crd时我个人的一些总结。 注意:我是使用goland开发,由于网络原因,一些包可能下载不下来,在goland中设置go的proxy,我是用的是https://goproxy.cn 使用kubebuilder开发crd。 kubebuilder安装: 官网: https://book.kubebuilder.io/q... 安装完毕之后,根据官网描述创建项目进行开发,开发之前建议先看一下以下链接的内容: https://www.cnblogs.com/alisy... 也可以从网上找一个kubebulder创建operator的例子进行参考。 关于operator-sdk以及kubebuilder的区别,参考以下链接: https://www.zhihu.com/questio... https://github.com/operator-f... 通过对上述两个不同的framework对crd进行开发,其实需要做的就是在controller的func (r *RedisClusterReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)方法下添加控制逻辑。 总结以下我个人开发operator的大致思路: 给有状态中间件做编排首先涉及到的就是kubernetes中的statefulset资源对象。 1)根据cr传递的属性值创建符合逻辑的statefulset,其中可能涉及到配置相关的configmap(configmap加载有延时,另外如果程序中如果不支持配置参数的热加载,可能需要在程序中进行处理)以及headless service以及普通service、PDB、PV、pvc等资源。 2)创建完上述资源之后,根据中间件各自的属性进行集群关系的组织 上述是个人开发operator历程的一些总结,其中还有很多没有涉及到方面,如有错误请多多指教。

June 2, 2020 · 1 min · jiezi

KubeOVN-120发布携手社区成员打造高性能容器网络

Kube-OVN1.2.0 新版本如期而至,支持 Vlan 和 OVS-DPDK 两种类型的高性能网络接口。本次发布得益于社区的壮大,感谢Intel爱尔兰开发团队与锐捷网络开发团队持续积极参与Kube-OVN开源社区贡献,将自身领域优势和实际应用相结合,加速打造高性能容器网络,推动更加稳定完整易用的Kubernetes网络体系在行业落地及发展。 •Release 文档: https://github.com/alauda/kube ... 1.2.0 1更高性能的容器网络 在之前的版本中,容器网络对外暴露需要管理员手动添加静态路由,从本版本开始,管理员可以通过最新的 BGP 功能对外发布 Pod 路由,方便外部直接通过 IP 访问 Pod。除此之外,子网的 CIDR 和网关类型可以动态进行修改,方便管理员动态调整网络配置。 新功能: 1.支持 vlan underlay 容器网络,可以达到更高的网络吞吐量和更低的网络延迟 2.支持 ovs-dpdk,DPDK 类型应用可以在 Pod 内运行 3.支持通过 BGP 协议对外发布路由 4.子网校验将会检查 CIDR 是否和 SVC 以及 Node 冲突 5.子网 CIDR 和网关类型可以进行动态调整 监控: 1.诊断脚本将会检查 apiserver 和 dns 工作状态 2.优化 Grafana 面板显示 其他: 1.修改上游 OVN 代码优化逻辑流数量 2.增加 arm64 支持 3.增加 k8s 1.18 支持 ...

June 2, 2020 · 1 min · jiezi

搭建Prometheus平台你必须考虑的6个因素

作者简介Loris Degioanni,Sysdig的创始人和CTO,同时还是容器安全工具Falco的创建者。 本文转自Rancher Labs 当前,Prometheus被许多企业和组织广泛使用,以监控其容器和微服务。但是在这一过程中,大型公司通常会陷入困境:当应用程序数量越来越多的时候,扩展监控指标则是一个十分重大的挑战。 不断增长的容器使情况复杂化相对来说,监控单体环境常常更简单,因为静态物理服务器和虚拟机数量是确定的,并且监控指标的数量也是有限的。但是,如今由于容器以及需要向微服务架构迁移,要跟踪监控的实例程序数量激增。 如果说位于数据中心的服务器是宠物,需要我们不断关注的话,那么云实例则更像牛(因为有很多,你不必关心单个实例),而容器则更像小蜜蜂。它们数量很多,有时每台机器有数百个容器,并且新的容器一直不断出现,当与诸如Kubernetes的容器编排引擎一起使用时,它们的寿命可能非常短。这使得跟踪监控它们变得更加困难,而且如果你不小心误操作的话,它们可能会造成很多损害。 随着复杂性和分布式环境的增加,你需要监控的实体数量也在增加。此外,你可能希望监控更多属性以确保你对正在发生的事情有准确的了解,或者在进行故障排除或事件响应的情况下,可以了解正在发生的事情。在短暂的环境中,后者尤其成问题,因为当你想了解问题的根本原因时,通常相关的资源已经停用,这意味着监控解决方案必须提供一种能够存储足够的历史记录以进行取证的方法。 流行的监控工具:Prometheus越来越多需要云监控的团队正在转向Prometheus,这是一个开源的CNCF项目。Prometheus已成为开发人员用来在云原生环境中收集和理解指标的首选监控工具。它由一个大型社区支持,有来自700多家公司的6300个贡献者,有13500个代码提交和7200个拉取请求。 默认情况下,典型的云原生应用程序堆栈(如Kubernetes、Ngnix、MongoDB、Kafka、golang等)会暴露Prometheus指标。Prometheus是一个可以垂直弹性伸缩的Go程序,为单个容器或单个主机部署它时十分容易。换言之,一开始使用Prometheus极为容易,你可以轻松监控你的第一个Kubernetes集群,但是这也意味着随着基础架构的增长,监控会越来越复杂。 应用程序增长带来的扩展问题随着环境规模增长,你需要跟踪监控飞速增长的时间序列数据,并且在数据量达到某个点之后,单个Prometheus实例无法继续跟踪监控。这一情况下,最直接的选择是在整个企业中运行一组Prometheus服务器,但这带来了一些挑战。例如,跨数十甚至数百台Prometheus服务器管理和合并数据并不容易。同样,了解企业工作流程、单点登录、基于角色的访问控制以及遵守SLA或合规性也不是容易的问题。随着应用程序的增长,在不中断开发人员工作的情况下运行一个全方位的监控解决方案,这将成为一个可管理性和可靠性的问题。 为了解决这一问题,企业采用了许多方法。 简单的方法是为每个命名空间或每个集群都准备一个单独的Prometheus服务器。这种方法到一定规模就会难以为继,此外,它还有一个缺点,那就是会造成大量的断开的数据孤岛。这会使故障排查变得很麻烦,因为大多数问题会跨越多个服务/团队/集群。不但在每个环境中很难找到相同的指标,你还需要把数据拼接在一起,以试图了解发生了什么。 另一个常见方法是使用类似Cortex或Thanos的开源工具来集合多个Prometheus服务器。这些高效的工具可以让你集中查询服务器、收集数据然后在统一的dashboard中共享。然而,与任何数据密集型分布式系统一样,它们需要大量的技能和资源才能运行。 需要考虑的6个因素对于那些以Prometheus为起点,然后寻求商业化解决方案以获得全局监控的公司来说,重要的是,不丢失Prometheus上完成的所有标准化开发工作——dashboard、告警、exporter等。然而,这不是需要考虑的唯一事情,如果你继续使用Prometheus,需要坚持以下标准: 1、 兼容性,以支持所有Prometheus功能你的供应商/所使用的工具/SaaS解决方案需要能够使用任何可产生Prometheus指标的实体程序中消耗数据,无论是本地Kubernetes还是云服务。相对来说,消耗Prometheus指标微不足道,但是也不要忽略一些小事情,例如将指标提取到存储中或增加数据时能够重新标注指标,这样对你的环境更有意义。这些小事加起来,能够收集到的数据将会堆积如山、大不相同。 2、 PromQL兼容性Prometheus查询语言由Prometheus创建者发明,用于提取存储在Prometheus中的信息。PromQL能让你查询指定服务或指定用户的指标,它还能汇总或细分数据。例如,你可以使用它显示所有容器中每个应用的CPU使用率。或者仅显示Cassandra容器的数据,并将其显示为每个集群的单个值。可以说,PromQL释放了Prometheus的真正价值,因此如果将Prometheus的指标集成到一个不完全支持PromQL的产品中,就完全违背了使用Prometheus的初衷。 3、 支持热插拔要真正与Prometheus兼容,该解决方案必须能够支持热插拔,以便能够与你现有的dashboard、告警和脚本一起使用。例如,许多使用Prometheus的企业都将Grafana用于dashboard。这个开源工具能够与Prometheus很好地集成在一起,包括在查询级别,并且可以用于生成一系列有用的图表和dashboard。因此,声称与Prometheus兼容的商业产品应与Grafana等工具兼容。仅仅说解决方案可以让你在Grafana中查看数字是远远不够的,你需要能够按照原样提取现有的Grafana dashboard,并将它们重新应用于商业解决方案中已安装的数据。 4、 访问控制在评估工具时,访问控制是另一个你需要考虑的安全问题。能够使用行业标准协议(包括LDAP、Google Oauth、SAML和OpenID)保护用户身份验证,使公司能够通过基于服务的访问控制来隔离和保护资源。 5、 故障排查Kubernetes简化了部署、弹性伸缩和管理容器化应用程序和微服务。这有助于保持服务的正常运行,但是要识别和解决诸如性能降低、部署失败和连接错误之类的根本问题,你需要能够从整个环境中收集和可视化基础架构、应用程序和性能数据。由于无法同时访问实时信息和上下文数据,因此几乎不可能关联环境中的指标,所以你可以更快地解决问题。 6、 与现有告警兼容最后,如果你正在寻找商业解决方案来帮助解决Prometheus可扩展性问题,请确保它支持所有级别的告警。能够实现这一目标的关键是全面支持Alert Manager功能,而Alert Manager还要求100%的集成和 PromQL兼容性。 如果你找到一个能够满足以上标准的商业化工具,你应该能够轻松将其集成到现有的Prometheus中,并且能够避免公司遇到的可扩展性问题。开发人员有充分的理由喜爱Prometheus,因此在采用商业化方案之前进行全面、尽职的调查将确保他们仍然可以使用自己喜欢的指标。

June 2, 2020 · 1 min · jiezi

k8s-job简介和访问

job 描述job是k8s提供的一种任务类型,负责批量处理短暂的一次性任务 (short lived one-off tasks),即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束 job的三种使用场景非并行任务:只启一个pod,pod成功,job正常结束并行任务同时指定成功个数:.spec.completions为指定成功个数,可以指定也可以不指定.spec.parallelism(指定>1,会有多个任务并行运行)。当成功个数达到.spec.completions,任务结束。有工作队列的并行任务:.spec.completions默认为1,.spec.parallelism为大于0的整数。此时并行启动多个pod,只要有一个成功,任务结束,所有pod结束参数completions指定job启动的任务(如:pod)成功运行completions次,job才算成功结束 parallelism指定job同时运行的任务(如:pod)个数,Parallelism默认为1,如果设置为0,则job会暂定 backoffLimitjob建议指定pod的重启策略为never,如:.spec.template.spec.restartPolicy = "Never",然后通过job的backoffLimit来指定失败重试次数 在达到backoffLimit指定的次数后,job状态设置为failed(默认为6次),重试时间采用指数规避(10s, 20s, 40s …),并限制在6分钟内 activeDeadlineSeconds通过指定job存活时间,来结束一个job。当job运行时间达到activeDeadlineSeconds指定的时间后,job会停止由它启动的所有任务(如:pod),并设置job的状态为failed, reason: DeadlineExceeded activeDeadlineSeconds的优先级高于backoffLimit apiVersion: batch/v1kind: Jobmetadata: name: pi-with-timeoutspec: backoffLimit: 5 activeDeadlineSeconds: 100 template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: NeverttlSecondsAfterFinished默认情况下,job异常或者成功结束后,包括job启动的任务(pod),都不会被清理掉,因为你可以依据保存的job和pod,查看状态、日志,以及调试等。这些用户可以手动删除,用户手动删除job,job controller会级联删除对应的pod 除了手动删除,通过指定参数ttlSecondsAfterFinished也可以实现自动删除job,以及级联的资源,如:pod。如果设置为0,job会被立即删除。如果不指定,job则不会被删除 apiVersion: batch/v1kind: Jobmetadata: name: pi-with-ttlspec: ttlSecondsAfterFinished: 100 template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never域名访问通过job的service或者pod域名来访问job的任务 ...

June 1, 2020 · 1 min · jiezi

技术分享-kubernetes-环境测试部署-MySQL-的随想

作者:王悦爱可生研发团队成员,负责数据库管理平台相关项目的开发和故障排查,好奇 MySQL 技术原理及各类数据库实现方案。本文来源:转载自公众号-图解 MySQL*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。注:阅读本文需要了解 pod,controller,service 等一些 kubernetes 的基本概念。什么是 kubernetes?有了容器技术后为什么还需要 kubernetes?容器凭借其良好的移植性,敏捷性和革命性的打包方式迅速成为云服务的新基础设施。但 Docker 毕竟只是 “container runtime”,我们需要一个编排框架作为系统核心来串联开发、测试、部署、运维等整个软件生命周期。kubernetes 就提供这样一个框架,提供大量容器的部署、编排、管理的能力。 如果将 MySQL 部署在 kubernetes 会有哪些挑战?带来了什么收益?虽然 kubernetes 社区一直在努力使得有状态应用成为一等公民,也推出了 statefulset 控制器支持 pod 的顺序部署,稳定的域名访问和存储访问。但鉴于 MySQL 部署运维的多样性和复杂性,在 kubernetes 上部署 MySQL 仍然要面临众多挑战。 1、业务流量入口的配置方式传统虚拟机环境下,我们通过虚 IP 的方式,让业务应用都配置事先定义的一个虚 IP 为链接数据库的地址,然后由高可用服务保证虚 IP 始终能被路由到 master 数据库。 在 kubernetes 中,出现了一层网络插件屏蔽了底层网络拓扑,高可用服务管理虚 IP 的方式需要随之适应调整,比如通过 service 结合标签完成虚 IP 的漂移,但 service 本身是 kubernetes 提供的一项功能,其可靠性和性能都取决于 kubernetes 服务的稳定。 以性能来说,service 是 kube proxy 组件通过配置 iptables 实现的,当 iptables 规则较多时不可避免的会产生时延,需要我们针对性的解决。 2、容器隔离带来的监控视野问题在 kubernetes 中,如果将 MySQL 制作为 container 运行在一个 pod 中,container 会将 MySQL 进程和运行环境隔离在一个单独的 namespace 中。监控组件在获取 MySQL 的一些 metirc 时,可能不得不进入与 MySQL 同一个 namespace 中,在部署和设计监控组件时需要考虑到这些限制。 ...

June 1, 2020 · 2 min · jiezi

k8s-v1150-秘钥过期保留部署重建集群

症状kubectl命令报错证书过期,无法新部署或者修改应用,运行中的应用状态正常。root@master:~# kubectl get poUnable to connect to server: x509: certificate has expired or is not yet valid 问题kubeadm自建证书有效期只有一年,可用下面命令查看,证书过期时间root@master:~# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep NotNot Before: Jun 14 08:37:50 2019 GMTNot After : Mar 5 02:50:42 2021 GMT解决(注:生产环境慎用,操作前先备份数据,避免造成灾难性损失)使用kubeadm alpha phase certs系令,重新生成证书,网上有很多文章(未验证) 在主节点上执行命令重新生成证书后,会导致集群不可用,所有应用都不可访问,由于需要快速恢复应用,放弃了后续操作保存ETCD数据,用kubeadm重建集群,快速恢复应用 备份数据,删除etcd /registry/secrets/kube-system/所有keys(不删除会导致新集群无法正常启动),用kubeadm init创建新集群,应用中配置过apiserver的证书也需要更新,最后测试应用是否正常

June 1, 2020 · 1 min · jiezi

实用教程丨使用K3s和MySQL运行Rancher-24

本文转自Rancher Labs 简 介本文将介绍在高可用K3s Kubernetes集群上安装Rancher 2.4的过程并针对MySQL利用Microsoft Azure数据库的优势,该数据库消除了对etcd的依赖,并为我们提供了Azure在这一服务中的所有其他功能。 在本文中,你将了解到只使用Azure Cloud Shell如何部署基础架构以支持此方式。使用Cloud Shell的好处是零基础架构即可上手——仅需访问Azure门户即可。并且许多所需的CLI功能已经预先安装好,从而大大减少了完成安装所需的工作量。 你部署完成基础架构后,你将了解如何使用K3s在一个Kubernetes集群上部署Rancher 2.4。在Rancher 2.4中,我们已经添加了新的部署支持模式:在两个节点上的Rancher 2.4运行带有外部数据库的K3s。使用这一模式的好处之一是我们可以将节点视为短暂的。由于K3s支持外部MySQL数据库,因此我们可以做到这一点。 K3s是一个轻量的Kubernetes发行版,它比Rancher Kubernetes Engine(RKE)更先进,并且具有以下增强功能: 嵌入式SQLite数据库替换了etcd,成为默认的数据存储,它还支持外部数据存储,例如PostgreSQL、MySQL和etcd。(本文中我们将使用MySQL)我们添加了简单但功能强大的“开箱即用”的功能,例如本地存储程序、服务负载均衡器、Helm controller以及Traefik controller。所有Kubernetes控制平面组件的操作都封装在单个二进制文件和进程中。这使K3s可以自动化和管理复杂的集群操作,例如分发证书。我们移除了in-tree云提供程序和存储插件我们已将外部依赖性降到最低(仅需要现代内核和cgroup挂载)。K3s软件包需要依赖项,包括:Containerd、Flannel、CoreDNS和主机实用程序(iptables、socat等)如果你是第一次尝试使用Rancher,可以考虑这种部署模式。这很有可能在之后成为部署Rancher的首选方法,提前了解总是好的——尤其是在Azure运行数据中心时。 前期准备为了完成以下内容,你需要提前准备: Microsoft账号:Microsoft的登录凭证。可以是你的Azure Active Directory凭据,也可以是普通的Outlook账户。访问一个Azure订阅:可以是免费试用/随用随付/也可以是企业订阅(https://azure.microsoft.com/e... )访问Azure门户(https://portal.azure.com/#home )架 构以下图片展示了将要在Azure中创建的资源: 这两个节点将放在单个子网(subnet)中的自己的vNet上。这些将在Azure负载平衡器的前面。MySQL数据库将从外部的vNet提供,vNet由Microsoft托管。然后通过连接到子网的单个网络安全组(NSG)保护节点。 Azure Cloud Shell我们将只使用Azure Cloud Shell来配置在Azure中的K3s上运行Rancher所需的所有元素。在门户中,单击右上角的“Azure Cloud Shell”按钮。该图标中有大于符号和下划线。 Azure网络资源组在Azure中,所有资源需要归属于某个资源组,所以我们得先创建资源组。我们将设置默认区域和资源组,以确保我们所有的资源都会被创建到正确的位置。 请注意:我使用eastus2作为我的区域,但你可以根据自身需要进行更改。 az group create -l eastus2 -n RancherK3sResourceGroupaz configure --defaults location=eastus2 group=RancherK3sResourceGroupVnet、公共IP和网络安全组(NSG)这些命令完成后,将在资源组内部创建网络组件。其中包括带有默认子网的vNet,我们稍后将创建的两个虚拟机(VM)的两个公共IP,以及一个网络安全组(NSG)。 az network vnet create --resource-group RancherK3sResourceGroup --name RancherK3sVnet --subnet-name RancherK3sSubnetaz network public-ip create --resource-group RancherK3sResourceGroup --name RancherK3sPublicIP1 --sku standardaz network public-ip create --resource-group RancherK3sResourceGroup --name RancherK3sPublicIP2 --sku standardaz network nsg create --resource-group RancherK3sResourceGroup --name RancherK3sNSG1az network nsg rule create -g RancherK3sResourceGroup --nsg-name RancherK3sNSG1 -n NsgRuleSSH --priority 100 \--source-address-prefixes '*' --source-port-ranges '*' \--destination-address-prefixes '*' --destination-port-ranges 22 --access Allow \--protocol Tcp --description "Allow SSH Access to all VMS."Azure负载均衡器我们在两个VM上安装K3s之后,我们需要一个负载均衡器来提供弹性并防止VM故障。 ...

June 1, 2020 · 3 min · jiezi

Kubernetes-容器入门基础开篇

什么是容器本质就是一种特殊的进程,用户的应用进程实际上就是容器里 PID=1 的进程技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”。对于 Docker 等大多数 Linux 容器来说,Cgroups 技术是用来制造约束的主要手段,而Namespace 技术则是用来修改进程视图的主要方法Linux 操作系统提供了 PID,Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作。Cgroups 对资源的限制能力也有很多不完善的地方,最多的自然是 /proc 文件系统的问题。容器的核心是隔离和限制,Namespace 的作用是“隔离”, Cgroups 的作用是“限制”。什么是Linux Cgroups全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等Cgroups 能够对进程进行优先级设置、审计,以及将进程挂起和恢复等操作Cgroups 的每一项子系统都有其独有的资源限制能力 blkio,为块设备设定I/O 限制,一般用于磁盘等设备;cpuset,为进程分配单独的 CPU 核和对应的内存节点;memory,为进程设定内存使用的限制docker创建过程启用 Linux Namespace 配置设置指定的 Cgroups 参数;切换进程的根目录(Change Root)docker的重要特性:一致性rootfs(根文件系统):挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。在 Linux 操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。由于 rootfs 里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。容器镜像中“层”的概念使用多个增量 rootfs 联合挂载一个完整 rootfs 的方案docker exec 是怎么做到进入容器里的?通过 setns() 函数可以将当前进程加入到已有的 namespace 中Volume机制允许你将宿主机上指定的目录或者文件,挂载到容器里面进行读取和修改操作,解决文件的挂载机制,同时保证了容器的隔离性不会被 Volume 打破。Kubernetes的核心设计思想?Pod Kubernetes 项目的原子调度单位,类似于传统环境中的虚拟机角色 凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段HostAliases:定义了 Pod 的 hosts 文件(比如 /etc/hosts)里的内容凡是跟容器的 Linux Namespace 相关的属性,也一定是 Pod 级别的Pod各种字段用法 ...

May 31, 2020 · 1 min · jiezi

使用VictoriaMetrics监控大规模Kubernetes集群

目前大多数关于Kubernetes集群监控的文章主要介绍如何使用Prometheus在Kubernetes集群上设置监控和报警系统,以及如何使用Grafana在其上建立出色的可视化系统。这本身就是一个很棒的系统,但是确实有一些问题,例如: 如果Prometheus异常怎么办?如果那是在关键阶段发生的呢?现在,可以通过部署多个Prometheus实例来解决此问题,但是仍然需要全局视图如果您需要分析旧的监控数据怎么办? Prometheus默认情况下仅将数据保留15天。因此,需要维护用于保持历史数据的数据库和查询系统。如果您的架构可扩展到数百个集群/环境,该怎么办?在这种情况下,将有多个Prometheus部署,并且同样需要全局视图。在扩展和创建高度可用的监控系统方面,存在很多问题。通过VictoriaMetrics解决所有问题。 可以将其无缝添加到现有Prometheus部署之上。而且,它提供了与Prometheus非常相似的仪表板,因此学习曲线很平。 本文主要介绍如何使用victoriametrics监控大规模Kubernetes 集群,并提供高可用,可扩展,全局视图等优势。 整体架构下图是整体架构图,主要包括4大块: 采集存储查询报警 整体架构图,可以让大家一目了然我们如何使用victoriametrics扩展Prometheus功能,从而完成对大规模集群的监控。 下面我们将对这4块一一解读。 采集Prometheus正在迅速成为Docker和Kubernetes监控工具之一。本节介绍包括Prometheus server,kube-state-metrics,各种用到的exporter,以及监控目标自动发现。 1 – Prometheus server 需要尽可能多的服务发现.有几种方法可以实现此目的::ConsulPrometheus Kubernetes SD 插件Prometheus operator 和Custom Resource Definitions2 – 除了应用程序指标,我们还希望Prometheus收集与Kubernetes服务,节点和业务流程状态相关的指标。Node exporter, 收集与主机相关的经典指标:cpu,mem,网络等Kube-state-metrics 收集架构和集群维度的指标: deployments, pod 指标, resource reservation等来自内部组件的Kube-system指标: kubelet, etcd, dns, scheduler等等关于该部分组件的安装和Promethues的配置相关,我们不做详细介绍。 更加云原生的话,可以使用prometheus-operator。Prometheus Operator能够帮助用户自动化的创建以及管理Prometheus Server以及其相应的配置。 当你的单个集群非常大的时候,我们可以考虑使用Prometheus relabel 中 hashmod 功能,实现采集对象的分片。不过必须为Prometheus配置remote_write才能将数据发送到VictoriaMetrics。将以下行添加到Prometheus配置文件(通常位于/etc/prometheus/prometheus.yml中): remote_write: - url: http://<victoriametrics-addr>:8428/api/v1/writePrometheus将传入的数据写入本地存储,并将其并行复制到远程存储。这意味着即使--storage.tsdb.retention.time持续时间内,数据在本地存储中仍然可用,即使远程存储不可用。 因为我们的VictoriaMetrics集群将服务多个Kubernetes集群的metrics,所以将以下行添加到Prometheus config的global部分中: global: external_labels: datacenter: k8s-cluster-01存储VictoriaMetrics是快速,经济高效且可扩展的时间序列数据库。可处理来自Kubernetes,IoT传感器,联网汽车,工业遥测,财务数据和各种企业工作负载的大量时间序列数据。可用作Prometheus的长期远程存储。 VictoriaMetrics 包括了如下的组件: vmstorage-- 存储数据。vminsert-- 通过remote_write API接收来自Prometheus的数据并将其分布在可用的vmstorage节点上。vmselect-- 通过从vmstorage节点获取并合并所需数据,通过Prometheus查询API执行传入查询。每个组件可以使用最合适的硬件配置独立扩展到多个节点。 整体架构图如下: ...

May 31, 2020 · 1 min · jiezi

k8s-hpa简介

HPAHPA全称Horizontal Pod Autoscaling ,可以实现pod的水平自动化扩缩容,比如当POD中业务负载上升的时候,可以创建新的POD来保证业务系统稳定运行,当POD中业务负载下降的时候,可以销毁POD来提高资源利用率。 HPA目前支持四种类型的指标,分别是Resource、Object、External、Pods。其中在稳定版本autoscaling/v1中只支持对CPU指标的动态伸缩,在测试版本autoscaling/v2beta2中支持memory和自定义指标的动态伸缩,并以annotation的方式工作在autoscaling/v1版本中。 refer: https://zhuanlan.zhihu.com/p/... metrics-serverk8s api-server的支持 - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key - --requestheader-allowed-names=front-proxy-client - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --requestheader-extra-headers-prefix=X-Remote-Extra- - --requestheader-group-headers=X-Remote-Group - --requestheader-username-headers=X-Remote-Usernotes:如果你未在 master 节点上运行 kube-proxy,则必须确保 kube-apiserver 启动参数中包含--enable-aggregator-routing=true部署metrics-server.yaml 参见下文,部署时注意nodeSelector是否匹配 nodeSelector: kubernetes.io/os: linux kubernetes.io/arch: "amd64"kubectl create -f metrics-server.yamlmetrics api手动获取指标 kubectl get --raw /apis/metrics.k8s.io/v1beta1/podsor [root@master01 hpa]# curl -H "Authorization: Bearer $toke" -k https://172.31.133.26:6443/apis/|grep metrics -C 5 { "name": "metrics.k8s.io", "versions": [ { "groupVersion": "metrics.k8s.io/v1beta1", "version": "v1beta1" } ], "preferredVersion": { "groupVersion": "metrics.k8s.io/v1beta1", "version": "v1beta1" } } ]}[root@master01 hpa]# curl -H "Authorization: Bearer $toke" -k https://172.31.133.26:6443/apis/metrics.k8s.io/v1beta1/pods |grep php -C 7 { "metadata": { "name": "php-apache-7bf64757b9-sh4rl", "namespace": "default", "selfLink": "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/php-apache-7bf64757b9-sh4rl", }, "containers": [ { "name": "php-apache", "usage": { "cpu": "31395n", "memory": "11988Ki" } } ] },CPU HPA创建应用kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80创建hpakubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10压测kubectl run -i --tty load-generator --image=busybox /bin/shHit enter for command promptwhile true; do wget -q -O- http://php-apache; done自动弹性[root@master01 msxu]# kubectl get hpa -wNAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEphp-apache Deployment/php-apache 0%/50% 1 10 1 52mphp-apache Deployment/php-apache 493%/50% 1 10 1 52mphp-apache Deployment/php-apache 493%/50% 1 10 4 52mphp-apache Deployment/php-apache 493%/50% 1 10 8 52mphp-apache Deployment/php-apache 493%/50% 1 10 10 53mphp-apache Deployment/php-apache 54%/50% 1 10 10 53mphp-apache Deployment/php-apache 49%/50% 1 10 10 54mphp-apache Deployment/php-apache 44%/50% 1 10 10 56mphp-apache Deployment/php-apache 0%/50% 1 10 10 57mphp-apache Deployment/php-apache 0%/50% 1 10 10 61mphp-apache Deployment/php-apache 0%/50% 1 10 9 61mphp-apache Deployment/php-apache 0%/50% 1 10 9 62mphp-apache Deployment/php-apache 0%/50% 1 10 1 62mMEM HPA创建HPAapiVersion: autoscaling/v2beta1kind: HorizontalPodAutoscalermetadata: name: php-apache-hpa namespace: defaultspec: scaleTargetRef: apiVersion: apps/v1beta1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 3 metrics: - type: Resource resource: name: memory targetAverageUtilization: 30查看[root@master01 hpa]# kubectl get hpaNAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEphp-apache Deployment/php-apache 0%/50% 1 10 1 5d17hphp-apache-hpa Deployment/php-apache 11%/30% 1 3 1 5d17h[root@master01 hpa]# kubectl describe hpa php-apache-hpa Name: php-apache-hpaNamespace: defaultLabels: <none>Annotations: <none>CreationTimestamp: Thu, 30 Apr 2020 17:57:40 +0800Reference: Deployment/php-apacheMetrics: ( current / target ) resource memory on pods (as a percentage of request): 11% (11546624) / 30%Min replicas: 1Max replicas: 3Deployment pods: 1 current / 1 desiredConditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from memory resource utilization (percentage of request) ScalingLimited False DesiredWithinRange the desired count is within the acceptable rangeEvents: <none>yamlmetrics-server.yaml 0.3.6 ...

May 30, 2020 · 3 min · jiezi

Kubernetes最佳实践之腾讯云TKE-集群组建

作者陈鹏,腾讯工程师,负责腾讯云 TKE 的售中、售后的技术支持,根据客户需求输出合理技术方案与最佳实践,为客户业务保驾护航。 使用 TKE 来组建 Kubernetes 集群时,会面对各种配置选项,本文将介绍几个比较重要的功能选型,给出对比与选型建议,让大家少走弯路。 Kubernetes 版本 Kubernetes版本迭代比较快,新版本通常包含许多 bug 修复和新功能,旧版本逐渐淘汰,建议创建集群时选择当前 TKE 支持的最新版本,后续出新版本后也是可以支持 Master 和节点的版本升级的。 网络模式: GlobalRouter vs VPC-CNI GlobalRouter 模式架构: •基于 CNI 和 网桥实现的容器网络能力,容器路由直接通过 VPC 底层实现; •容器与节点在同一网络平面,但网段不与 VPC 网段重叠,容器网段地址充裕。 VPC-CNI 模式架构: •基于 CNI 和 VPC 弹性网卡实现的容器网络能力,容器路由通过弹性网卡,性能相比 Global Router 约提高 10%; •容器与节点在同一网络平面,网段在 VPC 网段内; •支持 Pod 固定 IP。 网络模式对比: 支持三种使用方式: •创建集群时指定 GlobalRouter 模式; •创建集群时指定 VPC-CNI 模式,后续所有 Pod 都必须使用 VPC-CNI 模式创建; •创建集群时指定 GlobalRouter 模式,在需要使用 VPC-CNI 模式时为集群启用 VPC-CNI 的支持,即两种模式混用。 ...

May 29, 2020 · 2 min · jiezi

kubernetes-installation

kubeadm will do the following items: Preflight checkGenerate the keys and certs in /etc/kubernetes/pki# lsapiserver.crt apiserver-etcd-client.key apiserver-kubelet-client.crt ca.crt etcd front-proxy-ca.key front-proxy-client.key sa.pubapiserver-etcd-client.crt apiserver.key apiserver-kubelet-client.key ca.key front-proxy-ca.crt front-proxy-client.crt sa.keyGenerate the configuration file in /etc/kubernetes/xxx.conf/etc/kubernetes]$ls *.confadmin.conf controller-manager.conf kubelet.conf scheduler.confGenerate the yaml file to deploy kube-apiserver, kube-contaoller-manager, kube-scheduler, etcd.如下图所示,k8s clutser 包含如下的pod。此时还没有k8s cluster,那么这些pod是怎么deploy的么?答案就是Static Pod.这样设计就很舒服,完全是k8s方式。下面就看下各个pod yaml配置文件 // etcd.yamlapiVersion: v1kind: Podmetadata: annotations: kubeadm.kubernetes.io/etcd.advertise-client-urls: https://10.xx.xx.xx:2379 creationTimestamp: null labels: component: etcd tier: control-plane name: etcd namespace: kube-systemspec: containers: - command: - etcd - --advertise-client-urls=https://10.xx.xx.xx:2379 - --cert-file=/etc/kubernetes/pki/etcd/server.crt - --client-cert-auth=true - --data-dir=/var/lib/etcd - --initial-advertise-peer-urls=https://10.xx.xx.xx:2380 - --initial-cluster=localhost.localdomain=https://10.xx.xx.xx:2380 - --key-file=/etc/kubernetes/pki/etcd/server.key - --listen-client-urls=https://127.0.0.1:2379,https://10.xx.xx.xx:2379 - --listen-metrics-urls=http://127.0.0.1:2381 - --listen-peer-urls=https://10.xx.xx.xx:2380 - --name=localhost.localdomain - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - --peer-client-cert-auth=true - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - --snapshot-count=10000 - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt image: k8s.gcr.io/etcd:3.4.3-0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: host: 127.0.0.1 path: /health port: 2381 scheme: HTTP initialDelaySeconds: 15 timeoutSeconds: 15 name: etcd resources: {} volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs hostNetwork: true priorityClassName: system-cluster-critical volumes: - hostPath: path: /etc/kubernetes/pki/etcd type: DirectoryOrCreate name: etcd-certs - hostPath: path: /var/lib/etcd type: DirectoryOrCreate name: etcd-datastatus: {}// kubeapi serverapiVersion: v1kind: Podmetadata: annotations: kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.xx.xx.xx:6443 creationTimestamp: null labels: component: kube-apiserver tier: control-plane name: kube-apiserver namespace: kube-systemspec: containers: - command: - kube-apiserver - --advertise-address=10.xx.xx.xx - --allow-privileged=true - --authorization-mode=Node,RBAC - --client-ca-file=/etc/kubernetes/pki/ca.crt - --enable-admission-plugins=NodeRestriction - --enable-bootstrap-token-auth=true - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key - --etcd-servers=https://127.0.0.1:2379 - --insecure-port=0 - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key - --requestheader-allowed-names=front-proxy-client - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --requestheader-extra-headers-prefix=X-Remote-Extra- - --requestheader-group-headers=X-Remote-Group - --requestheader-username-headers=X-Remote-User - --runtime-config=api/all=true - --secure-port=6443 - --service-account-key-file=/etc/kubernetes/pki/sa.pub - --service-cluster-ip-range=10.96.0.0/12 - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key image: k8s.gcr.io/kube-apiserver:v1.18.0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: host: 10.xx.xx.xx path: /healthz port: 6443 scheme: HTTPS initialDelaySeconds: 15 timeoutSeconds: 15 name: kube-apiserver resources: requests: cpu: 250m volumeMounts: - mountPath: /etc/ssl/certs name: ca-certs readOnly: true - mountPath: /etc/pki name: etc-pki readOnly: true - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true hostNetwork: true priorityClassName: system-cluster-critical volumes: - hostPath: path: /etc/ssl/certs type: DirectoryOrCreate name: ca-certs - hostPath: path: /etc/pki type: DirectoryOrCreate name: etc-pki - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certsstatus: {}// kube-schedulerapiVersion: v1kind: Podmetadata: creationTimestamp: null labels: component: kube-scheduler tier: control-plane name: kube-scheduler namespace: kube-systemspec: containers: - command: - kube-scheduler - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf - --bind-address=127.0.0.1 - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true image: k8s.gcr.io/kube-scheduler:v1.18.0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: host: 127.0.0.1 path: /healthz port: 10259 scheme: HTTPS initialDelaySeconds: 15 timeoutSeconds: 15 name: kube-scheduler resources: requests: cpu: 100m volumeMounts: - mountPath: /etc/kubernetes/scheduler.conf name: kubeconfig readOnly: true hostNetwork: true priorityClassName: system-cluster-critical volumes: - hostPath: path: /etc/kubernetes/scheduler.conf type: FileOrCreate name: kubeconfigstatus: {}// kube-controller-managerapiVersion: v1kind: Podmetadata: creationTimestamp: null labels: component: kube-controller-manager tier: control-plane name: kube-controller-manager namespace: kube-systemspec: containers: - command: - kube-controller-manager - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf - --bind-address=127.0.0.1 - --client-ca-file=/etc/kubernetes/pki/ca.crt - --cluster-name=kubernetes - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key - --controllers=*,bootstrapsigner,tokencleaner - --horizontal-pod-autoscaler-sync-period=10s - --horizontal-pod-autoscaler-use-rest-clients=true - --kubeconfig=/etc/kubernetes/controller-manager.conf - --leader-elect=true - --node-monitor-grace-period=10s - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --root-ca-file=/etc/kubernetes/pki/ca.crt - --service-account-private-key-file=/etc/kubernetes/pki/sa.key - --use-service-account-credentials=true image: k8s.gcr.io/kube-controller-manager:v1.18.0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: host: 127.0.0.1 path: /healthz port: 10257 scheme: HTTPS initialDelaySeconds: 15 timeoutSeconds: 15 name: kube-controller-manager resources: requests: cpu: 200m volumeMounts: - mountPath: /etc/ssl/certs name: ca-certs readOnly: true - mountPath: /etc/pki name: etc-pki readOnly: true - mountPath: /usr/libexec/kubernetes/kubelet-plugins/volume/exec name: flexvolume-dir - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true - mountPath: /etc/kubernetes/controller-manager.conf name: kubeconfig readOnly: true hostNetwork: true priorityClassName: system-cluster-critical volumes: - hostPath: path: /etc/ssl/certs type: DirectoryOrCreate name: ca-certs - hostPath: path: /etc/pki type: DirectoryOrCreate name: etc-pki - hostPath: path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec type: DirectoryOrCreate name: flexvolume-dir - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certs - hostPath: path: /etc/kubernetes/controller-manager.conf type: FileOrCreate name: kubeconfigstatus: {}Once the above installation is done, the kubeadm will generate a bootstrap token. Any node with kubeadm and kubelet can join the cluster with this token.Once the token is generated, the kubeadm will store the ca.crt into etcd as configmap. the configmap name is cluster-info.$kubectl get cm cluster-info -n kube-public -o yamlapiVersion: v1data: kubeconfig: | apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01EVXhNakF4TURJek5Wb1hEVE13TURVeE1EQXhNREl6TlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS21hCmh3NDFTOStoVHZFc2ZXdVVib2RZQVFsSXdlYlljM3J1bUc4dzAyWTlWdHRJSWE4UFBJTHVJdG1ySCt1M0V4cUkKUmljQnhFQ3k1c09GT2srbFEzNHB5TkJGdWxUZmdldHNySUlIUC95dVYyeHVnVDRySW5aZyt2ckc4Y1NqWUtNaQpXdkREY2g2OC9UWllOd2xaNzgyOEYvdTF1SDdQOVhaZnFaQ01FcTU1ZWl1T1lMc3JudnJ6eml6MHBxakdlcXcvCkZXcmh0REo2M3pUMWVXUVcrSDdDaEZKSXpwc0ZoUmt5emNVQU1pWlNVTDBIUHc5amtWb2JWL1B5cVM1Wk9kdEUKV01VQk5Td3NPRDVXNGs4MTdhTXNvdGZiM3haMS9QL3NGUmhqdjEwc2w5bXNGMFJDcTgrenRVNW5CQ0dsdXFXdQpQT0ZDK2pHSnFwTlgwM3Bkam1rQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCTi8xSWtmd05nMlU2emU5UjB4d254eWRXQ1MKNEhLejdyQnBjcmxIbW0rSVIwekFMd3pJRi9yL2NJVHZlbzZTR3VrZ0E5OFhkM0lqckgwR0JzNmt0dWtEV1VobQp2dFp5U2V1cVpzemhPeEZXWVZFTlVzOEdteVBDZE1Wb1BSOFBlOWZudVFBQ2tQYWcrVXc1L2toNkFaZThEdi9ZCkdtcC9Xd1JleFlGcFBPMVhqWjBuUWtNcGhKMVFrVHdnK1dsK2JpWE1SVXNsVFViZk55TGtkUUdFSFJTVUF0Z1IKaFVFcHZGNU5UcVUrYk1uQm0wbGdDblBCNGc0WVl3Zm5UWWVzWHVFbkVvc05oUDl1UzFETEtHeXZPY3k1Qi9KRQphN2J1Z0pQWFZQd2crRkxnci9IZUQvcGI2VWpGTU13UHBoaFJPamNIY1pVWkpoeS82eHlpM3k3UkxyMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= server: https://10.xx.xx.xx:6443 name: "" contexts: null current-context: "" kind: Config preferences: {} users: nullkind: ConfigMapmetadata: creationTimestamp: "2020-05-12T01:03:03Z" managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:data: .: {} f:kubeconfig: {} manager: kubeadm operation: Update time: "2020-05-12T01:03:03Z" name: cluster-info namespace: kube-public resourceVersion: "190690" selfLink: /api/v1/namespaces/kube-public/configmaps/cluster-info uid: 816ef3fd-54b7-41ae-be4c-08d0e8359a40Install kube-proxy and dns plugin

May 29, 2020 · 4 min · jiezi

解构云原生初识Kubernetes-Service

编者按:云原生是网易杭州研究院(网易杭研)奉行的核心技术方向之一,开源容器平台Kubernetes作为云原生产业技术标准、云原生生态基石,在设计上不可避免有其复杂性,Kubernetes系列文章基于网易杭研资深工程师总结,多角度多层次介绍Kubernetes的原理及运用,如何解决生产中的实际需求及规避风险,希望与读者深入交流共同进步。 本文由作者授权发布,未经许可,请勿转载。 作者:李岚清,网易杭州研究院云计算技术中心资深工程师 为什么引入service众所周知,pod的生命周期是不稳定的,可能会朝生夕死,这也就意味着pod的ip是不固定的。 比如我们使用三副本的deployment部署了nginx服务,每个pod都会被分配一个ip,由于pod的生命周期不稳定,pod可能会被删除重建,而重建的话pod的ip地址就会改变。也有一种场景,我们可能会对nginx deployment进行扩缩容,从3副本扩容为5副本或者缩容为2副本。当我们需要访问上述的nginx服务时,客户端对于nginx服务的ip地址就很难配置和管理。 因此,kubernetes社区就抽象出了service这个资源对象或者说逻辑概念。 什么是serviceservice是kubernetes中最核心的资源对象之一,kubernetes中的每个service其实就是我们经常提到的“微服务”。 service定义了一个服务的入口地址,它通过label selector 关联后端的pod。service会被自动分配一个ClusterIP,service的生命周期是稳定的,它的ClusterIP也不会发生改变,用户通过访问service的ClusterIP来访问后端的pod。所以,不管后端pod如何扩缩容、如何删除重建,客户端都不需要关心。 (1)创建一个三副本的nginx deployment: nginx.yaml apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: nginxspec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx imagePullPolicy: Always name: nginx# kubectl create -f nginx.yamldeployment.extensions/nginx created# kubectl get pods -o widenginx-5c7588df-5dmmp 1/1 Running 0 57s 10.120.49.230 pubt2-k8s-for-iaas4.dg.163.org <none> <none>nginx-5c7588df-gb2d8 1/1 Running 0 57s 10.120.49.152 pubt2-k8s-for-iaas4.dg.163.org <none> <none>nginx-5c7588df-gdngk 1/1 Running 0 57s 10.120.49.23 pubt2-k8s-for-iaas4.dg.163.org <none> <none>(2)创建service,通过label selector关联nginx pod: ...

May 28, 2020 · 3 min · jiezi

Kubernetes-Ingress简单入门

本文转载自Rancher Labs 不知道你是否注意到一个奇怪的现象,尽管Kubernetes Ingress API仍然处于bata状态,但是已经有许多公司使用它来暴露Kubernetes服务。从事相关项目的工程师表示,Kubernetes Ingress API越来越有可能摘下其beta标签。实际上,Kubernetes Ingress API处于beta状态已经持续了几年的时间,准确来说,是在2015年秋季开始进入该阶段的。但是,漫长的beta阶段可以让Kubernetes贡献者有时间来完善规范并使其与已经搭建好的实施软件(HAProxy、NGINX、Traefik等)保持一致,从而使API标准化以反映最常见并且有需求的功能。 随着该功能GA的临近,那么现在应该是一个合适的时机可以帮助新手快速了解Ingress的工作方式。简而言之,Ingress是一个规则,可以绘制出在集群内部的服务如何弥合鸿沟,暴露到客户可以使用它的外部世界。同时,称为Ingress controller的代理在集群网络的边缘进行侦听(监视要添加的规则),并将每个服务映射到特定的URL路径或域名以供公众使用。在Kubernetes维护者开发API的同时,其他开源项目也实现了Ingress Controller并为其代理添加了自己的独特功能。 在本文中,我将介绍这些概念,并帮助你了解Ingress模式背后的驱动力。 路由问题在Kubernetes中创建Pod时,需要为其分配selector标签,如Deployment manifest的以下片段所示: 该Deployment创建了运行Docker镜像my-app的三个副本,并为其分配app=foo标签。除了直接访问Pod,通常将它们分组在Service下,这使它们可以在单个集群IP地址上使用(但是只能在同一集群中使用)。Service充当抽象层,隐藏了pod的周期短暂特性,可以随时增加或减少或替换它们。它还可以执行基本的循环负载均衡。 例如,以下Service定义收集所有带有selector标签app = foo的Pod,并在其中平均路由流量。 但是,只能从集群内部以及运行在附近的其他Pod访问此服务。Kubernetes Operator正在努力解决如何为集群外部的客户端提供访问权限。该问题在早期就已经出现,并且将两种机制直接集成到Service规范中进行处理。编写service manifest时,包括一个名为type的字段,该字段的值为NodePort或LoadBalancer。这是一个将类型设置为NodePort的示例: NodePort类型的服务使用起来很简单。本质上,这些服务希望Kubernetes API为他们分配一个随机的TCP端口,并将其暴露到集群之外。这样做的方便之处在于,客户端可以使用该端口将集群中的任何节点作为目标,并且他们的消息将被中转到正确的位置。这就类似于你可以拨打美国境内的任何电话,而接听电话的人都会确保为你转接到合适的人。 缺点在于,该端口的值必须介于30000到32767之间,虽然这个范围安全地避开了常用端口地范围,但是与常见的HTTP端口80和HTTPS 443相比,该端口显然不是很标准。此外,随机性本身也是一个障碍,因为它意味着你事先不知道值是什么,这使得配置NAT、防火墙规则更具挑战性——尤其是需要为每项服务设置不同的随机端口。 另一个选项是将类型设置为LoadBalancer。但是,这有一些前提条件——仅当你在GKE或EKS之类的云托管环境中运行并且可以使用该云供应商的负载均衡器技术时,它才有效,因为它是自动选择并配置的。其缺点是比较昂贵,因为使用这种类型的服务会为每个服务启动一个托管的负载均衡器以及一个新的公共IP地址,这会产生额外的费用。 Ingress路由分配一个随机端口或外部负载均衡器是很容易操作的,但也带来了独特的挑战。定义许多NodePort服务会造成随机端口混乱,而定义许多负载均衡器服务会导致需要支付比实际所需更多的云资源费用。这些情况不可能完全避免,但也许可以减少它的使用范围,甚至你只需要分配1个随机端口或1个负载均衡器就能够暴露许多内部服务。因此,这一平台需要一个新的抽象层,该层可以在入口点(entrypoint)后面整合许多服务。 那时,Kubernetes API引入了一种称为Ingress的新型manifest,它为路由问题提供了新的思路。它的工作方式是这样的:你编写一个Ingress manifest,声明你希望客户端如何路由到服务。manifest实际上并不自行执行任何操作,你必须将Ingress Controller部署到你的集群中,以监视这些声明并对其执行操作。 与其他任何应用程序一样,Ingress controller是Pod,因此它们是集群的一部分并且可以看到其他Pod。它们是使用在市场上已经发展了多年的反向代理搭建的,因此,你可以选择HAProxy Ingress Controller、NGINX Ingress Controller等。底层代理为其提供了第7层路由和负载均衡功能。不同的代理将自己的功能集放到表中。例如,HAProxy Ingress Controller不需要像NGINX Ingress Controller那样频繁地重新加载,因为它为服务器分配了slot,并使用Runtime API在运行时填充slot。这使得该Ingress Controller拥有更好的性能。 Ingress Controller本身位于集群内部,与其他Kubernetes Pod一样,也容易受到同一“监狱”的“监禁”。你需要通过NodePort或LoadBalancer类型的服务将它们暴露到外部。但是,现在你只有一个入口点,所有流量都将通过此处:一个服务连接到一个Ingress Controller,Ingress Controller依次连接到许多内部Pod。Controller具有检查HTTP请求的功能,可以根据其发现的特征(例如URL路径或域名)将客户端定向到正确的Pod。 参考这个Ingress的示例,该示例定义了URL路径/foo应该如何连接到名为foo-service的后端服务,而URL路径/bar被定向到名称为bar-service的服务。 如上文所示,你依旧需要为你的Pod设置服务,但是你不需要在Pod上设置类型字段,因为路由和负载均衡将由Ingress层处理。服务的作用被简化为以通用名称对Pod进行分组。最终,两个路径,/foo和/bar,将由一个公共IP地址和域名提供服务,例如example.com/foo 和 example.com/bar 。本质上,这是API网关模式,在API网关中,单个地址将请求路由到多个后端应用程序。 添加Ingress ControllerIngress manifest的声明式方法是你可以指定所需的内容,而无需知道如何实现。Ingress Controller的工作之一是执行,它需要监控新的ingress规则并配置其底层代理以制定相应的路由。 你可以使用Kubernetes包管理工具Helm安装HAProxy Ingress Controller。首先,通过下载Helm二进制文件并将其复制到PATH环境变量中包含的文件夹(例如/usr/local/bin/)中来安装Helm。接下来,添加HAProxy Technologies Helm库,并使用helm install命令部署Ingress Controller。 ...

May 26, 2020 · 1 min · jiezi

Kubernetes-Ingress实操带你见识Ingress模式背后的驱动力

导读:Ingress是一个规则,可以绘制出在集群内部的服务如何弥合鸿沟,暴露到客户可以使用它的外部世界。本文中,作者将帮助你了解Ingress模式背后的驱动力。 不知道你是否注意到一个奇怪的现象,尽管Kubernetes Ingress API仍然处于beta状态,但是已经有许多公司使用它来暴露Kubernetes服务。从事相关项目的工程师表示,Kubernetes Ingress API越来越有可能摘下其beta标签。 实际上,Kubernetes Ingress API处于beta状态已经持续了几年的时间,准确来说,是在2015年秋季开始进入该阶段的。但是,漫长的beta阶段可以让Kubernetes贡献者有时间来完善规范并使其与已经搭建好的实施软件(HAProxy、NGINX、Traefik等)保持一致,从而使API标准化以反映最常见并且有需求的功能。 随着该功能GA的临近,那么现在应该是一个合适的时机可以帮助新手快速了解Ingress的工作方式。简而言之,Ingress是一个规则,可以绘制出在集群内部的服务如何弥合鸿沟,暴露到客户可以使用它的外部世界。同时,称为Ingress controller的代理在集群网络的边缘进行侦听(监视要添加的规则),并将每个服务映射到特定的URL路径或域名以供公众使用。在Kubernetes维护者开发API的同时,其他开源项目也实现了Ingress Controller并为其代理添加了自己的独特功能。 在本文中,我将介绍这些概念,并帮助你了解Ingress模式背后的驱动力。 路由问题 在Kubernetes中创建Pod时,需要为其分配selector标签,如Deployment manifest的以下片段所示: 该Deployment创建了运行Docker镜像my-app的三个副本,并为其分配app=foo标签。除了直接访问Pod,通常将它们分组在Service下,这使它们可以在单个集群IP地址上使用(但是只能在同一集群中使用)。Service充当抽象层,隐藏了pod的周期短暂特性,可以随时增加或减少或替换它们。它还可以执行基本的循环负载均衡。 例如,以下Service定义收集所有带有selector标签app = foo的Pod,并在其中平均路由流量。 但是,只能从集群内部以及运行在附近的其他Pod访问此服务。Kubernetes Operator正在努力解决如何为集群外部的客户端提供访问权限。该问题在早期就已经出现,并且将两种机制直接集成到Service规范中进行处理。编写service manifest时,包括一个名为type的字段,该字段的值为NodePort或LoadBalancer。这是一个将类型设置为NodePort的示例: NodePort类型的服务使用起来很简单。本质上,这些服务希望Kubernetes API为他们分配一个随机的TCP端口,并将其暴露到集群之外。这样做的方便之处在于,客户端可以使用该端口将集群中的任何节点作为目标,并且他们的消息将被中转到正确的位置。这就类似于你可以拨打美国境内的任何电话,而接听电话的人都会确保为你转接到合适的人。 缺点在于,该端口的值必须介于30000到32767之间,虽然这个范围安全地避开了常用端口的范围,但是与常见的HTTP端口80和HTTPS 443相比,该端口显然不是很标准。此外,随机性本身也是一个障碍,因为它意味着你事先不知道值是什么,这使得配置NAT、防火墙规则更具挑战性——尤其是需要为每项服务设置不同的随机端口。 另一个选项是将类型设置为LoadBalancer。但是,这有一些前提条件——仅当你在GKE或EKS之类的云托管环境中运行并且可以使用该云供应商的负载均衡器技术时,它才有效,因为它是自动选择并配置的。其缺点是比较昂贵,因为使用这种类型的服务会为每个服务启动一个托管的负载均衡器以及一个新的公共IP地址,这会产生额外的费用。 Ingress路由 分配一个随机端口或外部负载均衡器是很容易操作的,但也带来了独特的挑战。定义许多NodePort服务会造成随机端口混乱,而定义许多负载均衡器服务会导致需要支付比实际所需更多的云资源费用。这些情况不可能完全避免,但也许可以减少它的使用范围,甚至你只需要分配1个随机端口或1个负载均衡器就能够暴露许多内部服务。因此,这一平台需要一个新的抽象层,该层可以在入口点(entrypoint)后面整合许多服务。 那时,Kubernetes API引入了一种称为Ingress的新型manifest,它为路由问题提供了新的思路。它的工作方式是这样的:你编写一个Ingress manifest,声明你希望客户端如何路由到服务。manifest实际上并不自行执行任何操作,你必须将Ingress Controller部署到你的集群中,以监视这些声明并对其执行操作。 与其他任何应用程序一样,Ingress controller是Pod,因此它们是集群的一部分并且可以看到其他Pod。它们是使用在市场上已经发展了多年的反向代理搭建的,因此,你可以选择HAProxy Ingress Controller、NGINX Ingress Controller等。底层代理为其提供了第7层路由和负载均衡功能。不同的代理将自己的功能集放到表中。例如,HAProxy Ingress Controller不需要像NGINX Ingress Controller那样频繁地重新加载,因为它为服务器分配了slot,并使用Runtime API在运行时填充slot。这使得该Ingress Controller拥有更好的性能。 ...

May 26, 2020 · 1 min · jiezi

根治Kubernetes存储头痛症的方法

为什么在云原生世界中,我们已经自动化了对这么多底层硬件复杂性的管理,所以存储仍然如此痛苦?原因是两个词:数据孤岛。 如果您已经在使用Kubernetes了,则可能有一个简单的原因:它使您的生活更轻松。毕竟,这是基于容器编排的整个前提。它让基础设施变得可支配,在需要时将其旋转,完成后将其丢弃,因此您不必考虑太多。至少,这就是应该起作用的方式。 如你所知,如果你已经建立起一个依赖于持久性数据的工作,你会马上遇到一个大问题——存储。 尽管Kubernetes完全抽象了计算和网络基础架构,但是当您的应用程序是有状态的并且数据是持久的时,它需要合适的方式进行存储。您仍必须了解底层存储基础架构的全部知识,才能找到所需数据的方式。 不仅是数据的位置,还有其他类型的存储基础结构附带的所有其他细粒度的考虑因素(性能,保护,弹性,数据治理和成本),大多数数据科学家都不想考虑。 为什么在云原生世界中,我们已经自动化了对这么多底层硬件复杂性的管理,所以存储仍然如此痛苦?原因是两个词:数据孤岛。 只要我们继续通过其赖以生存的不同基础架构来管理数据,而不是只关注数据本身,我们将不可避免地最终要花费大量的存储孤岛。幸运的是,这不是一个棘手的问题。通过将我们对数据管理的思考方式从以基础架构为中心的方法转变为以数据为中心的方法,我们可以使用Kubernetes首先给我们提供承诺:制作存储SEP(Someone Else‘s Problem)。 虚拟化您的数据 当您需要的数据散布在不同的存储孤岛上时,每个存储孤岛都有自己的独特属性(“或”或“云”,“本地”,“对象”,“高性能”等),根本无法抽象出基础架构注意事项。仍然有人必须回答所有有关性能,成本和数据治理的问题,才能建立您的管道。(如果该人是您要寻求帮助的IT管理员,您可以打赌他们每次在您的名字上出现您的名字时都会畏缩。因为他们知道他们将花费大量时间在神秘的基础结构接口上来破坏您的数据跨所有不同的副本和数据存储,而且他们根本无法在午餐前完成任务。 摆脱这种头痛的唯一方法-真正实现Kubernetes应该为您提供的速度和简便性的唯一方法-是虚拟化数据。基本上,您需要在数据和所有各种存储基础架构之间建立一个智能抽象层。该抽象层应该使您可以在任何地方查看和访问数据,而不必担心给定的基础架构是否具有适合您正在执行的操作的成本,位置或治理,也不必不断创建新副本。 做到这一点并不像听起来那么困难。关键:元数据。当您可以将所有数据需求,上下文或沿袭注意事项编码为随处可见数据的元数据时,那么在任何给定时刻驻留在哪个基础结构数据上就不再重要。现在,当您建立数据管道时,您可以完全使用元数据。而且您的虚拟化层可以使用AI / ML为您自动处理所有基础数据管理和基础结构注意事项。 利用基础架构抽象 一旦建立了虚拟化层,并通过元数据进行数据管理,就可以执行以前无法完成的各种事情。 1.消除数据孤岛:现在,您需要的数据位于哪个基础架构上或该基础架构位于什么位置都无所谓。对于您的应用程序,所有那些以前孤立的存储资源(本地,云,混合,归档)看起来就像一个通用的全局名称空间。 2.以编程方式访问存储资源:由于您在处理元数据(而不是一堆不同的底层硬件基础结构),因此您现在可以设置管道并通过声明性语句访问数据:我需要具有这种性能的数据,仅此而已真的很在乎。然后,智能虚拟化层就可以实现并实现,而您的应用程序(或您负担过重的IT管理员)则无需确切说明操作方法。 3.使数据管理实现自助服务:数据科学家无需担心比较不同存储类型的成本,启用数据保护或确保每次建立管道时都满足安全性和合规性要求。(因此,您的IT和安全团队可能也不希望数据科学家做出这些选择-除非他们希望所有内容都在最昂贵的存储上运行且没有适当的遵从性。)一旦将元数据和数据的管理分开,所有消失了。存储管理员可以通过配置一次基本策略来设置防护栏。然后,用户可以从此开始自助满足其大多数数据管理需求,而无需打开票证,并且不会在每次建立管道时手动进行这些调用时出现错误。 4.不断丰富您的数据:当系统支持可自定义的,可扩展的元数据时,您现在可以进行各种有趣的事情。例如,您可以构建递归流程,在其中通过系统运行数据,获取一些结果,将这些结果添加回元数据,然后再次运行作业。您可以开始对数据周围的数据建立深入的上下文理解。处理和使用的数据越多,将来用于其他作业的数据就越丰富。而且,对于要使用它的任何其他应用程序或数据科学家来说,现在,智能总是随处可见。它并不局限于一个副本,而是藏在某个地方的一个存储孤岛上。 解开数据 当您虚拟化数据时,所有这些事情都是可能的,因为与孤立的存储基础架构相比,元数据的使用更加灵活。设置和编排数据管道所伴随的存储注意事项现在可以为您解决。您的存储资源将变为可编程的,自助服务的并且自动合规,通常不需要手动干预。 突然之间,您实际上生活在这样一个现实,即Kubernetes和软件定义的存储始终应该交付。无论基础架构如何,存储都是软件定义的,可编程的并且在混合云环境中保持一致。您的数据更丰富,更灵活。您的IT团队不再将ID卡上的爆炸照片留在墙上扔镖。最重要的是,您实际上在处理数据上花费了更多时间,而不用担心数据的存放位置。

May 26, 2020 · 1 min · jiezi

通过Kubernetes实现边缘计算的3种选择

导语:企业对边缘计算有不同的看法,但很少有人排除他们将来将应用程序组件部署到边缘的可能性,特别是对于物联网和其他低延迟应用程序。 许多组织还认为Kubernetes是在边缘计算环境中运行容器的理想机制,尤其是那些已经为满足其云和数据中心需求而采用了容器编排系统的公司。 在边缘计算中使用Kubernetes的:3个通用规则是: 规则1:避免使用缺乏资源池的边缘模型,因为Kubernetes在这些环境中不会提供任何真正的好处。这是因为Kubernetes专为管理集群中的容器部署而设计,也就是说集群是一种资源池。 规则2:将边缘Kubernetes视为更广泛的Kubernetes部署中的特殊用例。 规则3:除非存在大量的边缘资源池,否则请避免使用专门为边缘托管设计的Kubernetes工具。 除了这3个通用规则外,还有三个主要的部署选项可以在边缘环境中运行Kubernetes和容器。 选项1:公有云 在此模型中,公有云提供商托管边缘环境或者该环境是公有云服务的扩展。 此选项的典型用例是增强云前端中的交互性。在这种情况下,边缘是公有云的扩展,并且组织的Kubernetes部署实践应适合云提供商的产品。云提供商对边缘计算的支持可能涉及与提供商的公有云服务集成的本地边缘设备,例如Amazon Snowball。 公有云边缘托管几乎总是通过将云托管选项之一(VM,容器或无服务器功能)扩展到边缘来支持,这意味着Kubernetes不会将边缘视为单独的集群。这种方法很容易实现,但可能需要Kubernetes托管策略(例如亲和力,污点和容忍度)将边缘组件定向到边缘资源。小心; 如果边缘计算的目标是减少延迟,请不要让边缘资源与它们控制的元素相距太远。 在边缘计算架构中,数据在网络外围进行处理-尽可能靠近其原始源。 选项2:数据中心外的服务器设施 这种方法涉及在组织自己的数据中心外部的一个或多个服务器设施中进行边缘部署。 该边缘模型的主要用例是工业物联网,其中存在大量的边缘处理要求-至少足以证明将服务器放置在工厂和仓库等位置是合理的。在这种情况下,有两种选择:将每个边缘托管点视为一个单独的群集,或者将边缘托管仅视为主数据中心群集的一部分。 在边缘托管支持各种应用程序的情况下(这意味着每个边缘站点都是真正的资源池),请考虑使用专门的Kubernetes发行版,例如KubeEdge,它针对以边缘为中心的任务进行了优化。确定您的边缘应用程序是否与数据中心Kubernetes部署紧密结合,以及在某些情况下边缘和数据中心是否会备份其他应用程序。 在许多边缘部署中,边缘几乎充当仅运行专用应用程序而不运行资源池的客户端。在这种情况下,可能不需要集成Kubernetes集群。否则,请考虑使用Kubernetes联合身份验证作为统一边缘和数据中心策略进行部署的方法。 选项3:专用器具 在这种情况下,边缘模型由一组专用于工厂或加工设施的专用设备组成。 许多专用的边缘设备基于ARM微处理器,而不是基于以服务器为中心的Intel或AMD芯片。在许多情况下,这些设备与IoT设备紧密相连,这意味着每个边缘设备都有自己的传感器和控制器社区来管理。这里的应用程序不是可变的,因此总体上来说,无论是容器化还是专门用于Kubernetes部署,收益都较少。该模型最常见的用例是智能建筑。 非服务器边缘设备通常与为较小的设备占用空间而设计的Kubernetes版本相关联,例如K3s。但是,某些专用边缘设备可能根本不需要编排。如果设备可以同时或分别运行多个应用程序,或者这些设备中的一组托管协作应用程序组件,则可以考虑使用K3来协调部署。如果这两个条件都不成立,则根据需要将应用程序简单地加载到具有本地或网络存储的设备上。 在某些情况下,应用程序的边缘组件与数据中心中运行的应用程序组件紧密结合。这可能需要管理员同步部署边缘和数据中心组件,并在两者上使用通用的编排模型。在这种情况下,要么将边缘元素合并到主数据中心群集中,然后使用策略将边缘组件托管定向到正确的位置,要么将边缘分离为单独的群集,然后通过联盟对其进行部署和编排。 最终确定,容器和业务流程是有效使用资源池的工具。对于边缘计算模型在边缘创建小型服务器场的企业而言,Kubernetes和边缘计算是很好的合作伙伴,与主要的Kubernetes部署联合的,单独的,特定于边缘的Kubernetes策略是个好主意。 如果边缘环境更加专业,但是仍然必须结合主要应用托管资源(无论是在云还是数据中心中)进行部署和管理-将边缘作为一种主机类型适合现有的Kubernetes部署。如果边缘是专业的并且在很大程度上是独立的,则考虑完全不在边缘计算中使用容器。

May 26, 2020 · 1 min · jiezi

示例如何将配置信息传入Pod

在K8s中经常需要将一些公用配置信息传入各个Pod。配置信息可以写在.toml文件中,通过其内容作为secret挂载在Pod的volume下进行访问直接上示例common.toml文件内容如下 [Mysql]UserName = "developer"Password = "123456"IpHost = "192.168.112.11:8902"DbName = "contract"[etcd]addrs = ["121.11.199.160:2379","121.11.199.161:2379","121.11.199.162:2379"]执行命令将common.toml内容加载到k8s集群 kubectl create secret -n mytest generic common-config --from-file=./common.toml -o yaml --dry-run | kubectl apply -n mytest -f -testconfig.yaml内容如下 apiVersion: v1kind: Podmetadata: name: configtest-podspec: containers: - name: configtest-container image: busybox command: ["sh", "-c"] args: - while true; do if [[ -e /etc/config/common.toml ]]; then echo -en '\n\n'; cat /etc/config/common.toml; fi; sleep 5; done; volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume secret: secretName: common-config items: - key: common.toml path: common.toml生成Pod ...

November 5, 2019 · 1 min · jiezi

Pod数据传递

<1>使用环境变量传递参数在.yaml文件的container部分使用 env:- name: DEMO_PARAM1 value: "Parameter from the environment"设置参数podenv.yaml内容如下 apiVersion: v1kind: Podmetadata: name: podenv-demo labels: purpose: demo-podenvspec: containers: - name: podenv-demo-container image: busybox env: - name: DEMO_PARAM1 value: "Parameter from the environment" command: ["/bin/sh"] args: ["-c", "while true; do echo $(DEMO_PARAM1); sleep 10; done"]执行命令 kubectl apply -f podenv.yaml进入pod kubectl -it exec podenv-demo /bin/sh查看参数 printenv可看到传入的参数 ...DEMO_PARAM1=Parameter from the environment...<2>使用Secret创建Secret kubectl create secret generic test-secret --from-literal=username='admin' --from-literal=password='testsecret123'将secret数据作为文件在pod中通过volume访问secretpod-volume.yaml内容如下 apiVersion: v1kind: Podmetadata: name: secret-test-podspec: containers: - name: test-container image: nginx volumeMounts: - name: secret-volume mountPath: /etc/secret-volume volumes: - name: secret-volume secret: secretName: test-secret生成pod执行命令 ...

November 5, 2019 · 3 min · jiezi

阿里巴巴-Kubernetes-应用管理实践中的经验与教训

导读:云原生时代,Kubernetes 的重要性日益凸显。然而,大多数互联网公司在 Kubernetes 上的探索并非想象中顺利,Kubernetes 自带的复杂性足以让一批开发者望而却步。本文中,阿里巴巴技术专家孙健波在接受采访时基于阿里巴巴 Kubernetes 应用管理实践过程提供了一些经验与建议,以期对开发者有所帮助。在互联网时代,开发者更多是通过顶层架构设计,比如多集群部署和分布式架构的方式来实现出现资源相关问题时的快速切换,做了很多事情来让弹性变得更加简单,并通过混部计算任务来提高资源利用率,云计算的出现则解决了从 CAPEX 到 OPEX 的转变问题。 云计算时代让开发可以聚焦在应用价值本身,相较于以前开发者除了业务模块还要投入大量精力在存储、网络等基础设施,如今这些基础设施都已经像水电煤一样便捷易用。云计算的基础设施具有稳定、高可用、弹性伸缩等一系列能力,除此之外还配套解决了一系列应用开发“最佳实践”的问题,比如监控、审计、日志分析、灰度发布等。原来,一个工程师需要非常全面才能做好一个高可靠的应用,现在只要了解足够多的基础设施产品,这些最佳实践就可以信手拈来了。但是,在面对天然复杂的 Kubernetes 时,很多开发者都无能为力。 作为 Jira 和代码库 Bitbucket 背后的公司,Atlassian 的 Kubernetes 团队首席工程师 Nick Young 在采访中表示: 虽然当初选择 Kubernetes 的战略是正确的(至少到现在也没有发现其他可能的选择),解决了现阶段遇到的许多问题,但部署过程异常艰辛。那么,有好的解决办法吗? 太过复杂的 Kubernetes“如果让我说 Kubernetes 存在的问题,当然是‘太复杂了’”,孙健波在采访中说道,“不过,这其实是由于 Kubernetes 本身的定位导致的。” 孙健波补充道,Kubernetes 的定位是“platform for platform”。它的直接用户,既不是应用开发者,也不是应用运维,而是“platform builder”,也就是基础设施或者平台级工程师。但是,长期以来,我们对 Kubernetes 项目很多时候都在错位使用,大量的应用运维人员、甚至应用研发都在直接围绕 Kubernetes 很底层的 API 进行协作,这是导致很多人抱怨 “Kubernetes 实在是太复杂了”的根本原因之一。 这就好比一名 Java Web 工程师必须直接使用 Linux Kernel 系统调用来部署和管理业务代码,自然会觉得 Linux “太反人类了”。所以,目前 Kubernetes 项目实际上欠缺一层更高层次的封装,来使得这个项目能够对上层的软件研发和运维人员更加友好。 如果可以理解上述的定位,那么 Kubernetes 将 API 对象设计成 all-in-one 是合理的,这就好比 Linux Kernel 的 API,也不需要区分使用者是谁。但是,当开发者真正要基于 K8s 管理应用、并对接研发、运维工程师时,就必然要考虑这个问题,也必然要考虑如何做到像另一层 Linux Kernel API 那样以标准、统一的方式解决这个问题,这也是阿里云和微软联合开放云原生应用模型 Open Application Model (OAM)的原因。 ...

November 5, 2019 · 2 min · jiezi

阿里云和微软共同开源的-OAM-对-Kubernetes-开发人员意味着什么

上周,微软和阿里巴巴共同推出了开放应用模型(OAM),用于定义部署在任何地方的应用模型的一种规范。Rudr是Microsoft基于Kubernetes环境的OAM标准实现。 我用了一个周末来了解OAM试图解决的问题,为此我还以Rudr为基础重构了一些我喜欢的基础微服务的应用程序。本文和以下教程将帮助普通的Kubernetes用户了解OAM背后的动机。 众所周知,Kubernetes是一个复杂的平台,包含许多活动组件。在编排和部署简单的两层Web应用程序时,需要涉及到创建Storage Classes,PVC,PV,Secret,ConfigMap,Service,Deployment和 Ingress。在实际生产部署中还需要健全的日志收集,监控告警,安全性,高可用性和可扩容性,我们将用到StatefulSet(有状态应用),网络策略,RBAC,准入控制,Pod横向自动伸缩等知识。 对于从传统IT环境过渡的开发工程师和运维工程师,Kubernetes强劲的发展势头让人感到害怕。甚至一些熟悉容器化的DevOps专业人员都发现想要完全理解Kubernetes也是个很棘手的事情。 当转换为可部署的文件时,一个简单的两层Web应用程序可能具有十几个YAML文件,里面包含了这个应用程序针对于每个对象的定义描述。 Kubernetes的核心设计原则之一是对象的可解耦性。例如一个服务可以独立于Pod而存在,创建一个PV无需任何使用者,还可以配置一个无需任何后端来处理请求的Ingress。基于一组标签,注释和选择器,这些特点在运行时可以拼凑在一起共同使用。一个服务会将请求转发到符合条件的一个或多个Pod上。Ingress将流量路由到某个服务也是相同的用法。 Kubernetes中的每个对象都是自我治理并且完全独立的。尽管这种设计使Kubernetes具有极高的可扩展性,但其缺点是缺乏应用程序上下文关系。Kubernetes中的一个应用程序是一系列协同工作的自治对象的集合。当转换为可部署的文件时,一个简单的两层Web应用程序可能具有十几个YAML文件,里面包含了这个应用程序针对于每个对象的定义描述。在单一环境下管理和维护这些编排文件是与Kubernetes接触时面临的最大挑战。 Helm工具想要通过图表的概念来解决这个问题。但是即使这样,你往往还是在部署后丢失上下文关系。毕竟Helm只是应用程序运行所需的多个Kubernetes对象定义的集合编排文件生成工具。 Kubernetes的其他挑战之一是开发人员和运维人员之间有个很模糊的界限。为了有效利用平台,开发人员需要对运行时环境有一定的了解。他们需要了解ConfigMap如何对Pod中包装的容器可见。他们需要知道初始化代码的哪一部分应打包为Init容器。运维人员负责确保正确的命名规则来保证服务发现的正常工作。他们需要知道需要传递给Pod的所有环境变量。运维人员应根据应用程序的特性来决定将容器部署为ReplicationController,DaemonSet还是StatefulSet。他们需要在生产环境部署的时候,选择使用ClusterIP还是NodePort。 如上所述,开发人员期望熟悉运行时程序需要哪些必要的决策,并且运维人员应了解软件设计方面的知识。OAM想要通过以下方法解决这些存在的问题: 将应用程序上下文带入微服务部署在开发人员和运维人员之间明确关注点与运行时无关的应用程序模型从更高的层次上来说,OAM是用于定义微服务或一组属于应用程序的微服务组件的规范。每个组件都有一个或多个工作节点,它们可以作为一个服务,或者是个消费者,或者是个需要完成的任务。每个工作节点之间可能具有关联的配置和特征。这些配置转换为传递给工作节点的参数,这些特性会影响组件的运行环境,同一类组件的集合属于一个应用程序。 OAM的核心前提是,开发人员的工作以从源代码在构建容器镜像的时候结束,而运维人员负责的工作正好从此处开始。Ops团队将负责为单个应用程序的一组容器镜像进行配置和部署。 OAM中的组件意在使开发人员能够以与基础结构无关的格式声明,来区分执行单元的操作特性。组件定义了在基础系统结构中的CPU,GPU,内存和磁盘需求。 组件中的每个工作节点类型如下: 配置通常在处理后以参数的形式传递给工作节点。例如在配置中定义了发送到应用程序服务工作节点的连接数据库的字符串。 这些特性定义了工作节点的运行时行为,从而定义了一个应用程序。Rudr就是OAM的参考实现的,并有以下特征: 如果我们仔细观察Workload和Trait的概念描述,它们可以轻松将这些概念对应到到Kubernetes。服务本质上是Deployment,而Singleton服务是具有一个replica的Deployment。它们都要使用ClusterIP或NodePort。Worker和单独的Worker是没有关联服务的Pods。任务是一个可并行化的Kubernetes Job,而单个任务是个单次运行的Job。 同样这些特性也能对应到到Kubernetes的自动扩容,Ingress,Deployment和PVC等概念。 因此使用OAM和Rudr,开发人员可以提交代码并构建可转换为工作节点的容器镜像。运维人通过这些组件的特性进行配置定义,将其组成工作节点。 从技术上讲,OAM这一规范可以适用于虚拟机基础设施平台(IaaS),PaaS和容器管理平台(CaaS)。OAM的每个构建模块都可以映射到相应的环境。就是说OAM定义的YAML文件可以在没有任何修改的情况下部署在任何环境中。 在本系列的下一篇文章中,我将带你逐步了解Rudr的端到端教程,其中展示了以Node.js Web应用程序部署组件,配置其特性所涉及的工作流程。敬请关注~ 作者|Janakiram MSV翻译|Big dimple原文链接 https://thenewstack.io/what-does-the-open-application-model-oam-and-rudr-mean-for-kubernetes-developers/ 已获原作者授权翻译转载 “ 阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术公众号。”

November 4, 2019 · 1 min · jiezi

Kubernetes中限制Java容器内存资源实践

0x00 起因公司最近部分应用要从 Docker Swarm 迁移到 Kubernetes,而迁移到新的 Kubernetes 上的应用都要做资源的限制,否则如果 Pod 不断地占用机器资源把整个节点都拖垮了那就很糟糕了。。所以我按照 Kubernetes 的文档做了限制后,发现并没有什么卵用,容器不断的被 OOMKIILED 然后又重启,服务也一直无法访问,所以需要研究下Java 应用到底该怎么限制内存资源。 0x01 分析当我在 google 搜索了一波后,发现这个问题就是JVM 无法得知容器的资源限制,所以按照 JVM 的默认规则,它分配的 Max Heap Size 是系统内存的1/4,所以就很容易超出 resource limits 的限制,导致容器被 kill 掉。 而造成这个问题的原因是什么呢,这就得说回 Docker 容器,我们都知道 Docker 容器本质上就是一个被隔离的用户态进程,而构成这个进程自然就少不了三驾马车: cgroups 做进程的资源限制namespace 做命名空间隔离aufs 做联合文件挂载实现文件系统我们要限制 Java 程序自然就与 cgroups 有关了,在 Linux 上,一切皆文件,所以系统的资源信息等也是以一种特殊的文件形式放在/proc目录下的,像我们常用的一些top,free,ps等查看系统资源的工具本质上也是从这个目录下获取的信息。但是 cgroups 限制资源不一样,它是在/sys/fs/cgroups目录下对指定 namespace 的做限制。 而我们的 JVM 是怎么获取到的当前进程的内存信息的呢?是通过读取挂载的/proc/meminfo文件了,那么由于/proc/meminfo里面展示的是宿主机的内存资源,从而让容器产生了自己是地主的感觉,还以为有大把的内存可以给它用,其实自己只是一个长工。。 0x02 方法了解了这个问题的成因后,并在网上搜集了一些资料,我发现解决这个问题的方式就是在 Java 启动命令前加上JVM_OPTS参数,而具体加什么参数和 Java 的版本有关,总的来说呢,规则如下: Java < Java8_u131: 如果低于这个版本,那么在 Java 容器的 CMD 命令里得加上具体的内存分配大小,如"-Xms64M -Xmx256M",注意-Xms最好不超过 Pod 限制资源3/4,因为不止是 JVM 要使用内存,容器本身也是需要内存的。Java < 10 : 如果 Java 版本在这个区间,那么我们就不需要明确地指定最大堆的大小了,这几个版本实际上已经可以从 cgroups 获取资源限制信息,只不过这个特性需要手动开启,需要加上参数"-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1"如果 Java 版本大于 10 : 恭喜你,这个特性是默认开启的其他下游 Java 分支: 不太清楚,请查看官方文档0x03 实践我司 Java 容器启动方式有两种,一种是通过 jar 包启动,还有一种是用 Tomcat启动,所以我会分别介绍这两种 Java 应用的资源限制方式。 ...

November 2, 2019 · 1 min · jiezi

从零开始入门-K8s-Kubernetes-网络概念及策略控制

作者 | 阿里巴巴高级技术专家  叶磊 一、Kubernetes 基本网络模型本文来介绍一下 Kubernetes 对网络模型的一些想法。大家知道 Kubernetes 对于网络具体实现方案,没有什么限制,也没有给出特别好的参考案例。Kubernetes 对一个容器网络是否合格做出了限制,也就是 Kubernetes 的容器网络模型。可以把它归结为约法三章和四大目标。 约法三章的意思是:在评价一个容器网络或者设计容器网络的时候,它的准入条件。它需要满足哪三条? 才能认为它是一个合格的网络方案。四大目标意思是在设计这个网络的拓扑,设计网络的具体功能的实现的时候,要去想清楚,能不能达成连通性等这几大指标。约法三章先来看下约法三章: 第一条:任意两个 pod 之间其实是可以直接通信的,无需经过显式地使用 NAT 来接收数据和地址的转换;第二条:node 与 pod 之间是可以直接通信的,无需使用明显的地址转换;第三条:pod 看到自己的 IP 跟别人看见它所用的IP是一样的,中间不能经过转换。后文中会讲一下我个人的理解,为什么 Kubernetes 对容器网络会有一些看起来武断的模型和要求。 四大目标四大目标其实是在设计一个 K8s 的系统为外部世界提供服务的时候,从网络的角度要想清楚,外部世界如何一步一步连接到容器内部的应用? 外部世界和 service 之间是怎么通信的?就是有一个互联网或者是公司外部的一个用户,怎么用到 service?service 特指 K8s 里面的服务概念。service 如何与它后端的 pod 通讯?pod 和 pod 之间调用是怎么做到通信的?最后就是 pod 内部容器与容器之间的通信?最终要达到目标,就是外部世界可以连接到最里面,对容器提供服务。 对基本约束的解释对基本约束,可以做出这样一些解读:因为容器的网络发展复杂性就在于它其实是寄生在 Host 网络之上的。从这个角度讲,可以把容器网络方案大体分为 Underlay/Overlay 两大派别: Underlay 的标准是它与 Host 网络是同层的,从外在可见的一个特征就是它是不是使用了 Host 网络同样的网段、输入输出基础设备、容器的 IP 地址是不是需要与 Host 网络取得协同(来自同一个中心分配或统一划分)。这就是 Underlay;Overlay 不一样的地方就在于它并不需要从 Host 网络的 IPM 的管理的组件去申请 IP,一般来说,它只需要跟 Host 网络不冲突,这个 IP 可以自由分配的。为什么社区会提出 perPodperIP 这种简单武断的模型呢?我个人是觉得这样为后面的 service 管理一些服务的跟踪性能监控,带来了非常多的好处。因为一个 IP 一贯到底,对 case 或者各种不大的事情都会有很大的好处。 ...

October 17, 2019 · 2 min · jiezi

Kubernetes权威指南――从Docker到Kubernetes实践全接触

网站更多书籍文章点击进入>> CiCi岛 下载<font color=red>电子版仅供预览及学习交流使用,下载后请24小时内删除,支持正版,喜欢的请购买正版书籍</font> <font color=blue>电子书下载</font>(皮皮云盘-点击“普通下载”)<font color=blue>购买正版</font>封页 内容简介从PaaS平台建设和运维的角度去理解、分析和解决问题,囊括了Docker入门、Kubernetes技术架构及核心原理、网络及存储方案、行业实践指南、PaaS生态链以及发展趋势等方面的内容,图文并茂、内容丰富、由浅入深、讲解全面,具有很强的可借鉴性。 目 录序前言第1章 Docker简介 11.1 什么是Docker 11.2 为什么要用Docker 31.3 Docker基本概念 41.3.1 镜像 41.3.2 容器 61.3.3 镜像仓库 81.4 Docker架构及原理 81.4.1 Docker架构 81.4.2 Docker原理 111.4.3 容器网络 151.4.4 容器存储 161.5 Docker安装 161.5.1 手动安装模式 171.5.2 Ubuntu中自动化安装Docker 181.5.3 CentOS中自动化安装Docker 19第2章 容器引擎 212.1 容器引擎实现原理 222.2 容器生命周期管理 292.3 容器状态管理 332.4 访问运行状态容器 352.5 访问容器内容 36第3章 镜像管理 373.1 Dockerfile及镜像制作 373.1.1 Dockerfile的作用 373.1.2 Dockerfile文件构成 373.1.3 常用命令集 383.1.4 构建镜像 383.2 镜像基本操作 383.2.1 从镜像仓库下载镜像 383.2.2 将本地镜像上传到镜像仓库 393.2.3 查看本地镜像 393.2.4 导出和导入本地镜像 403.2.5 构建镜像 413.2.6 修改本地镜像标识 423.2.7 删除本地镜像 423.3 Dockerfile优化 423.3.1 Dockerfile检查项 423.3.2 Dockerfile优化实例 433.3.3 检查及优化工具 443.4 操作系统基础镜像制作 443.4.1 操作系统版本选择 453.4.2 操作系统参数调整 453.4.3 确定基础rpm包范围 453.4.4 确定常用命令范围 463.4.5 操作系统镜像制作过程 483.4.6 系统资源限制配置说明 493.5 容器镜像安全加固 493.5.1 容器安全加固规范 493.5.2 安全检查工具 51第4章 镜像仓库管理 524.1 Docker Registry 524.1.1 Docker Hub 524.1.2 第三方公共仓库 534.1.3 建立私有镜像仓库 534.2 Harbor 544.2.1 Harbor架构 554.2.2 Harbor的镜像同步机制 564.2.3 Harbor用户认证 564.2.4 Harbor容器镜像安全扫描 574.2.5 Harbor部署实战 57第5章 Docker相关部署实践 595.1 MySQL Docker部署实践 595.1.1 MySQL简介 595.1.2 MySQL为什么要容器化部署 605.1.3 MySQL容器化操作实践 605.2 Docker支持GPU实践 625.2.1 GPU简介 625.2.2 CPU与GPU的对比 635.2.3 通过nvidia-docker使用GPU 63第6章 Kubernetes简介 656.1 PaaS简介 656.1.1 传统PaaS系统 656.1.2 基于Docker的新型PaaS平台 676.2 为什么需要Kubernetes 696.3 Kubernetes的由来 696.3.1 Kubernetes的特点 696.3.2 Kubernetes的历史 706.4 Kubernetes核心概念 71第7章 Kubernetes架构和部署 737.1 Kubernetes架构及组件 737.1.1 Master节点 737.1.2 Node节点 757.1.3 调度控制原理 767.1.4 集群功能模块间的通信 767.1.5 Kubernetes高可用方案 777.2 Kubernetes部署方案总结 77第8章 Pod相关核心技术 818.1 Pod 818.1.1 Pod定义文件详解 818.1.2 基本操作 838.1.3 Pod与容器 858.1.4 镜像 868.1.5 其他设置 868.1.6 Pod调度 898.1.7 Pod生命周期 908.2 Label 928.3 Replication Controller和Replica Set 938.3.1 RC定义文件详解 938.3.2 RC与Pod的关联——Label 958.3.3 弹性伸缩 978.3.4 滚动升级 988.3.5 新一代副本控制器Replica Set 1008.4 Horizontal Pod Autoscaler 1018.5 Deployment 1028.6 Job 1058.7 StatefulSet 1068.7.1 使用StatefulSet 1068.7.2 扩容/缩容StatefulSet 1088.8 ConfigMap 1108.9 健康检查 1128.9.1 流程健康检查 1128.9.2 应用健康检查 112第9章 Kubernetes Service 1149.1 容器及Pod间通信 1159.2 kube-proxy 1179.3 DNS服务发现机制 1189.4 Headless服务 1199.5 Kubernetes服务 1209.5.1 ClusterIP 1229.5.2 NodePort 1239.5.3 LoadBalancer 1259.5.4 Ingress 1259.6 网络策略 1279.7 完整的Kubernetes服务发布实践 1289.7.1 各Kubernetes集群LoadBalancer服务发布 1309.7.2 Ingress服务发布 1329.7.3 服务发现 133第10章 Kubernetes网络 13410.1 单主机Docker网络通信 13410.1.1 Host模式 13510.1.2 Container模式 13510.1.3 None模式 13610.1.4 Bridge模式 13610.1.5 基础网络模型的优缺点分析 13710.2 跨主机Docker网络通信 13710.2.1 Flannel网络方案 13910.2.2 Calico网络方案 14010.2.3 利用Kuryr整合OpenStack与Kubernetes网络 14310.2.4 网络方案对比分析 144第11章 Kubernetes存储 14511.1 存储使用场景 14511.2 文件存储的几种形式 14611.3 Flex Volume存储管理方案 14811.3.1 为什么需要灵活存储组件 14811.3.2 如何实现灵活存储组件 14811.4 标准化容器存储接口CSI 149第12章 安全及多租户配额管理 15012.1 API服务器认证 151 ...

October 15, 2019 · 2 min · jiezi

近万字案例文Rancher-VMware-PKS实现全球数百站点的边缘K8S集群管理

Sovereign Systems是一家成立于2007年的技术咨询公司,帮助客户将传统数据中心技术和应用程序转换为更高效的、基于云的技术平台,以更好地应对业务挑战。曾连续3年提名CRN,并且在2012年到2016年均被评为美国增长最快的私营公司之一。本文由Sovereign Systems的解决方案架构师Chip Zoller根据客户的使用案例撰写而成 Rancher是一个容器编排管理平台,它已经在这一领域深耕几年并且具备很多简单易用的实用功能。近几年,它经过重构已经完全拥抱Kubernetes。在本文中,我将着重介绍如何在VMware Enterprise PKS之上构建一个企业级、高可用和安全的Rancher Server安装。同时,我将回答“为什么要在PKS上使用Rancher”这一问题。此外,本文将包括整个构建流程、架构以及完整的安装指南。涉及的内容十分丰富,赶紧开始吧! 把Rancher部署在PKS上?我知道这并不是一个普遍的搭配,特别是这两个解决方案还存在某种竞争关系。它们都能够在不同的云提供商部署Kubernetes集群,并可以在本地部署到诸如vSphere之类的堆栈。它们分别都有自己的长处和短处,但是在管理空间中两者没有重叠的地方。Enterprise PKS使用BOSH部署Kubernetes集群,并且继续将其用于生命周期的事件——扩展、修复、升级等。而Rancher则是将自己的驱动程序用于各种云PaaS解决方案,甚至使用vSphere进行本地部署来执行类似的任务。但Rancher能够导入外部配置的集群并且为其提供可见性,至今PKS还没有实现这样的功能。而在VMware 2019大会上,VMware宣布推出一款名为Tanzu Mission Control的产品,该产品在未来或许能实现Rancher现有的这些功能。但是,在那之前,Rancher依旧代表着优秀的技术,它可以管理并且聚合不同的Kubernetes集群到单一的系统中。 这个案例从何而来?和我之前写过的很多文章一样,这篇文章也是从客户项目中衍生出来的。而且由于找不到关于这个主题的Enterprise PKS指南,我决定自己写一个。这个客户计划使用裸机、小型硬件将在边缘的Kubernetes部署到全球数百个站点。他们需要将所有集群统一到一个工具中,从而方便管理、监控以及应用程序部署。他们在主要的数据中心运行Enterprise PKS,来为其他业务需求部署Kubernetes集群。由于这些站点都与他们在世界各地的各个数据中心相连接,因此它们需要聚集在一个可以在本地运行的工具中,同时必须具有高可用性、安全性和高性能。将Enterprise PKS用于底层、专用的Kubernetes集群,然后在该集群上以HA模式在Rancher Server上分层,这样操作为我们两个方面的绝佳功能——通过NSX-T进行网络和安全性,通过BOSH进行集群生命周期维护,通过Harbor复制镜像仓库并且通过Rancher在边缘范围内对分散的Kubernetes集群在单一窗格进行统一管理。 架 构我们先来看看架构图。 理论上说,我们在底部有一个vSphere栈,它在我们本地的SDDC中托管这个环境。接下来,我们通过PKS构建了一个3-master和3-worker的Kubernetes集群。除了许多其他系统容器(未在上图显示)之外,worker还托管Rancher pod和Nginx pod。基于以上,我们使用NSX-T提供的负载均衡器来提供两个主要虚拟的服务器:一个用于控制平面访问,另一个用于ingress访问。 然而,经过反复的试验并最终失败之后,我发现NSX-T的L7负载均衡器并不支持Rancher正常运行所需的必要请求头。具体来说,Rancher需要在HTTP请求中传递4个请求头到pod。这些请求头用于识别入站请求的来源,并确保在应用程序外部已经发生适当的TLS终止。其中一个请求头X-Forwarded-Proto,它可以告诉Rancher用于与负载均衡器进行通信的协议,但NSX-T的负载均衡器无法传递这些请求头。基于此,我们必须使用第三方ingress controller——nginx,它是目前最流行的解决方案之一,它对大部分的客户端选项提供了广泛的支持,并且可以直接发送请求头。 我们接着往下一个层次看,进入Kubernetes内部(如下图所示)。请记住,我们正在专门研究worker,但正在抽象化诸如节点之类的物理层。 外部请求通过Nginx controller中的LoadBalance服务类型进入集群。从该服务构建的端点列表中选择一个nginx controller,进而匹配ingress controller中的规则。该请求将转发到Rancher Service,最后到与该服务上的标签selector匹配的pod。 我们接下来一步一步完成安装过程,看完之后你将会有更深的理解。 安 装请记住上文提到的架构,我们将开始将这些碎片拼在一起。一共有6个大步骤,每个步骤下都有详细的小步骤,我会详细说明。 1、 配置新的自定义PKS集群 第一步,我们将专门为Rancher制定一个plan,然后构建一个专门用于在HA模式下运行Rancher的集群。我们还将制作一个自定义的负载均衡器配置文件,以供构建中参考。 2、 使用Helm准备集群 集群构建完成之后,我们需要进行准备,以便可以使用Helm的软件包,因为我们将使用它来安装ingress controller和Rancher。 3、 生成证书和secret 这是一个企业级的部署,这意味着要使用自定义证书。所以我们需要创建那些证书并且使它们可供Kubernetes的各种API资源使用。 4、 创建并配置Ingress 既然我们无法使用NSX-T作为Ingress controller,那么我们必须配置另一种类型并适当地配置它。然后我们将使用一个NSX-T的Layer-4负载均衡器来发送流量到ingress。 5、 安装Rancher 接下来,我们使用Helm安装Rancher。 6、 配置基础架构 一切都就位之后,我们需要执行一些部署后的配置任务,然后才完成所有的步骤。 接下来,我将详细解释每一个步骤具体如何操作。 配置新的自定义PKS集群首先我们需要做的是设置PKS基础架构,以便我们可以将Kubernetes集群部署在任意地方。需要做两件最基础的事情:创建一个新plan,创建中型负载均衡器。我们的plan需要指定3个master以使控制平面级别高可用,并且3个worker在工作负载级别高可用。在本例中,由于我们正在准备将大量集群安装到Rancher中,因此我们可能要继续进行操作,并指定一个中型负载均衡器,否则PKS会给我们一个很小的负载均衡器。这个负载均衡器将为控制平面/API访问提供虚拟服务器并将traffic发送到Rancher。 在PKS tile中,我使用以下配置创建一个新plan。 根据你自己的需求来创建plan,但记住master和worker的数量。如果想要将其放入生产环境中,我建议你增加master永久磁盘的规格。既然每个主节点都是一个包含控制平面组件和etcd的组合节点,并且Rancher将充分利用Kubernetes集群的etcd安装作为其数据存储,因此我们要确保有足够的空间。 你可以使用底部的附加组件部分来自动加载任意Kubernetes Manifest,使其可以在集群构建过程中运行。我将使用pks-dns,它可以在控制平面启动后自动为其创建DNS记录。如果你之前尚未使用过,我强烈建议你试用一下。 最后,为了让Rancher agent能够正确运行,请务必在此集群上启动“允许特权”模式。 ...

October 15, 2019 · 4 min · jiezi

K8S-生态周报-Docker-19033-DNS-不再区分大小写

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。 文末有活动,欢迎参与。Docker 19.03.3 正式发布在本周 Docker 发布了 19.03.3 版本,这个版本的变更内容 很重要,我会将主要内容都列出来。(上周周报介绍了 19.03.3-rc1 的一些情况) 已知问题DOCKER-USER iptables 链丢失;如果你并不需要在 DOCKER-USER 链上定义规则的话,那你也并不会受此问题的影响。 临时解决办法:手动添加丢失的链,操作如下: iptables -N DOCKER-USERiptables -I FORWARD -j DOCKER-USERiptables -A DOCKER-USER -j RETURN这个问题会在 19.03.4 中进行修复, 很快会进行发布; 实际会把 libnetwork 中有问题的那段代码先去掉。 如果已经升级了此版本的用户,受到此问题影响的话,可以使用上述方式进行临时解决。 安全问题将 runc 更新到了 v1.0.0-rc8-92-g84373aaa 这其中包含了 runc 中对 CVE-2017-18367 的修复,该漏洞的根本原因在于 libseccomp-golang 中一个错误的逻辑运算 ,有兴趣的朋友可以点开链接看看实际的修复代码,并且也可以发现该代码其实在 2017 年 4 月就已经合并进 libseccomp-golang 的主干中了,但实际上在今年 6 月在 runc 中才真正修复。这个问题其实反映出来的是当我们在维护项目时,对自己所用的各种依赖需要有所了解和把握,整体来讲,尽可能避免依赖项过旧是个好事儿;并且安全问题非常值得关注。 常规更新修改了仍使用 schema1 进行镜像 push/pull 操作时的通知逻辑,早在今年 6 月份我推送的周报中就已经提到过建议升级至 schema2 来获得长久的支持,以及更好的兼容性。具体的升级版本之一就是使用最新版的 Docker, 将镜像 pull 后再重新 push 即可(适用于大多数情况);根据 RFC4343 Docker 修改了内部 DNS 的逻辑,使其符合了 RFC4343 的规范, DNS 开始不再区分大小写了 。如果在实际使用中有依赖大小写解析的情况,请及时修改逻辑。对此版本感兴趣的朋友可以参考 ReleaseNote ...

October 14, 2019 · 1 min · jiezi

重启-Kubernetes-Pod的几种方式

0x00 前言在使用 docker 的过程中,我们可以使用docker restart {container_id}来重启容器,但是在 kubernetes 中并没有重启命令(没有 kubectl restart {podname}),有时候我们的 Pod 出现 Bug意外终止,导致我们需要重启 Pod ,却没有一个很好的方式,特别是没有 yaml 文件的情况下,所以我总结了以下几种重启 Pod 的方式。 0x01 方法 1有最新的 yaml 文件。 在有 yaml 文件的情况下可以直接使用kubectl replace --force -f xxxx.yaml 来强制替换Pod 的 API 对象,从而达到重启的目的。如下图: 0x02 方法 2没有 yaml 文件,但是使用的是 Deployment 对象。 kubectl scale deployment esb-admin --replicas=0 -n {namespace}kubectl scale deployment esb-admin --replicas=1 -n {namespace}由于 Deployment 对象并不是直接操控的 Pod 对象,而是操控的 ReplicaSet 对象,而 ReplicaSet 对象就是由副本的数目的定义和Pod 模板组成的。所以这条命令分别是将ReplicaSet 的数量 scale 到 0,然后又 scale 到 1,那么 Pod 也就重启了。 ...

October 14, 2019 · 1 min · jiezi

K8s-从懵圈到熟练-–-集群网络详解

导读:阿里云 K8S 集群网络目前有两种方案:一种是 flannel 方案;另外一种是基于 calico 和弹性网卡 eni 的 terway 方案。Terway 和 flannel 类似,不同的地方在于 terway 支持 Pod 弹性网卡,以及 NetworkPolicy 功能。本文中,作者基于当前的 1.12.6 版本,以 flannel 为例,深入分析阿里云 K8S 集群网络的实现方法。鸟瞰总体上来说,阿里云 K8S 集群网络配置完成之后,如下图所示:包括集群 CIDR、VPC 路由表、节点网络、节点的 podCIDR、节点上的虚拟网桥 cni0、连接 Pod 和网桥的 veth 等部分。 类似的图大家可能在很多文章中都看过,但因为其中相关配置过于复杂,比较难理解。这里我们可以看下这些配置背后的逻辑。 基本上我们可以把这些配置分三种情况来理解:集群配置,节点配置以及 Pod 配置。与这三种情况对应的,其实是对集群网络 IP 段的三次划分:首先是集群 CIDR,接着是为每个节点分配 podCIDR(即集群 CIDR 的子网段),最后在 podCIDR 里为每个 Pod 分配自己的 IP。 集群网络搭建初始阶段集群的创建,基于云资源 VPC 和 ECS,在创建完 VPC 和 ECS 之后,我们基本上可以得到如下图的资源配置。我们得到一个 VPC,这个 VPC 的网段是 192.168.0.0/16,我们得到若干 ECS,他们从 VPC 网段里分配到 IP 地址。 ...

October 9, 2019 · 2 min · jiezi