翻译自:https://blog.heptio.com/core-kubernetes-jazz-improv-over-orchestration-a7903ea92ca原作者：Joe Beda (Dad of two. CTO of Heptio. Started Google Compute Engine, Kubernetes and Google Container Engine.)本篇文章讲述了Kubernetes内部组件的工作原理，及创建POD的流程。如果你是运维人员或者是Kubernetes的使用者，你可以不需要知道Kubernetes的内部工作原理，但是如果你想理解Kubernetes内部的工作原理，这篇文章非常适合你。读这篇文章的前提是，你已经大致了解并会运用Kubernetes。这篇文章不会去描述什么是Kubernetes及其组件（如：Pod, Node, Kubelet）。 本篇将讨论Kubernetes核心组件及这些核心组件是如何让Kubernetes 对"爵士乐即兴演奏"。通常将像Kubernetes这样的通用系统称为容器的 "管弦乐编排"。但是管弦乐编排，必须有一个预先计划的指挥家。因此，这并不是Kubernetes的一个好的描述。相反，Kubernetes更像是爵士乐即兴演奏，有一系列演员互相配合协调完成演奏。接下来，开始介绍每个核心组件的功能。然后将看一个典型的调度和启动一个Pod的流程。1. Datastore: EtcdEtcd是Kubernetes的存储状态的数据库。虽然Kubernetes系统中有重要的内存缓存，但Etcd被认为是记录系统状态。Etcd的快速总结：它是一个集群分布式数据库，它可以提供分布式数据的一致性。这类的系统（如Zookeeper, Consul）是在 Google开发的chubby系统之后形成的，这些系统也称为"锁服务器"，因为他们可以实现分布式锁。Etcd和chubby的数据模型是一个简单的层次化的Key，并存储了简单的非结构化value，这看起来像是一个文件系统。有意思的是，在Google, chubby 被频繁用于为实现访问本地文件和对象存储的功能的抽象文件接口。然而，分布式数据库的高度一致性，提供了数据的严格写入顺序并允许client原子性的对数据做更新操作。可靠的系统的状态管理是任何系统中非常困难的一件事情。在分布式系统中，它是更加困难的，因为它引入了一致性算法，如raft或paxos。通过使用etcd，Kubernetes可以专注系统的其他部分。Etcd的watch机制是Kubernetes工作的关键。系统允许client去执行轻量级的对于Key值变化事件的订阅。当要watch的数据发生变化时, client会立即得到通知。这可以用作分布式系统组件之间的协调机制。 一个组件一旦写入etcd，其他组件可以立即对该变化作出反应。Etcd的消息机制正好和PubSub消息队列机制相反。在许多消息队列系统系统中，topic不存储真正的用户数据，但发布到这些topic的消息含有丰富的数据。对于像Etcd这样的系统，Key（类似于主题）存储了真实的数据而消息（数据变化通知）不含独特的丰富消息。换句话说，对于消息队列来说，topic很简单，而像Etcd则正好相反。（译者认为此处概括的非常准确）2. Policy Layer: API ServerKubernetes的核心组件是API Server，它是Kubernetes系统和Etcd直接对话的唯一组件。实际上，etcd是API server的实现细节，理论上也可以用其他分布式存储系统来支持Kubernetes.API server是一个策略组件，提供对Etcd的过滤访问。它的作用本质上是相对通用的，目前正在被分解处理。因此，API Server也可以用于其他系统的控制平面。API server的主要货物是资源，通过暴露简单的REST API 向外提供服务。这些资源有一个标准结构可以实现一些扩展功能。无论如何，API Server，允许各类组件创建，读取，写入，更新，和监视资源。API Server的具体的功能：认证和授权。Kubernetes有一个可插拔的认证系统。有一些内置的用户认证机制和授权这些用户访问资源。此外，还有一些方法可用于向外部服务提供这些服务。这种可扩展性是Kubernetes构建的核心功能。API Server运行一组可以拒绝或修改请求的准入控制器。 这些允许策略被应用并设置默认值。 这是确保在API Server客户端仍在等待请求确认时进入系统的数据有效性的关键。 虽然这些准入控制器目前正在编译到API Server中，但目前正在进行的工作是使其成为另一种可扩展性机制。API Server 有助于API 版本控制。API 版本的一个关键问题是允许资源的字段的改变，字段添加，弃用，重新组织和以其他方式转换。 API Server在Etcd中存储资源的"true"表示，并根据满足的API版本转换/呈现该资源。 自项目早期开始，规划版本控制和API的发展一直是Kubernetes的一项重要工作。API Server 一个重要特性是支持watch机制。这意味着API Server的客户端可以使用与Etcd相同的协调模式。Kubernetes中的大多数协调包括写入另一个组件正在监视的API服务器资源的组件。 第二个组件将对几乎立即发生的变化做出反应。3. 业务逻辑：Controller Manager and Scheduler这些是通过API Server 进行协调的组件。这些称为Controller Manager和Scheduler的组件绑定到单独的服务器Master上Scheduler组件将做许多事情让系统工作：查找未分配给节点的Pod(未绑定的Pod)；检查集群的状态（缓存在内存中）；选择具有空闲空间并满足其他约束条件的节点;将pod绑定到该节点。Controller Manager 组件，实现ReplicaSet的行为。（ReplicaSet可以确保任何时候都可以运行一个Pod模板的副本数量）。控制器将根据资源中的选择器 监控ReplicaSet 资源和一组Pod。为了保持在ReplicaSet中稳定的一组Pod，控制器将创建、销毁Pod。4.Node Agent: Kubelet每一个Node上都有一个Agent。这也像其他组件一样对API Server进行身份验证。Agent负责监视绑定到其节点的一组Pod，并确保这些Pod正常运行，并且能实时返回这些Pod的运行状态。5.典型的流程为帮助理解，创建Pod的整个流程，时序图如下：这个时序图展示了创建pod的流程，基本的流程如下：用户提交创建Pod的请求，可以通过API Server的REST API ，也可用Kubectl命令行工具，支持Json和Yaml两种格式；API Server 处理用户请求，存储Pod数据到Etcd；Schedule通过和 API Server的watch机制，查看到新的pod，尝试为Pod绑定Node；过滤主机：调度器用一组规则过滤掉不符合要求的主机，比如Pod指定了所需要的资源，那么就要过滤掉资源不够的主机；主机打分：对第一步筛选出的符合要求的主机进行打分，在主机打分阶段，调度器会考虑一些整体优化策略，比如把一个Replication Controller的副本分布到不同的主机上，使用最低负载的主机等；选择主机：选择打分最高的主机，进行binding操作，结果存储到Etcd中；kubelet根据调度结果执行Pod创建操作： 绑定成功后，会启动container, docker run, scheduler会调用API Server的API在etcd中创建一个bound pod对象，描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步bound pod信息，一旦发现应该在该工作节点上运行的bound pod对象没有更新，则调用Docker API创建并启动pod内的容器。总结通过使用API Server作为中心协调点，Kubernetes能够以松耦合的方式，实现组件相互交互。 希望读完此文，你可以对Kubernetes创建Pod的原理有更深入的认识。此外：k8s 也提供qos 服务，ref: https://cloud.90.vc/s/8WCqPHRH55AgMYY
环境准备操作系统：centos 7 1908 mini设置主机名hostnamectl set-hostname k8s-sh-21.vm.90.vc hostnamectl set-hostname k8s-sh-22.vm.90.vc hostnamectl set-hostname k8s-sh-23.vm.90.vc配置hostsvim /etc/hosts10.0.2.21 k8s-sh-21.vm.90.vc 10.0.2.22 k8s-sh-22.vm.90.vc 10.0.2.23 k8s-sh-23.vm.90.vc防火墙与selinux主机防火墙需要开放相应端口，具体可参考kubernetes官方文档 Check required ports 一节。这里为了方便，直接关闭防火墙systemctl stop firewalld systemctl disable firewalld目前为止，kubernetes还不支持selinux，所以必须将selinux关闭。将 SELinux 设置为 permissive 模式（相当于将其禁用）setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config关闭swap分区自kubernetes1.8版本开始，要求必须关闭swap，否则kubelet无法启动修改/etc/fstab配置文件，注释掉swap行。执行以下操作，关闭swap。swapoff -a sysctl -w vm.swappiness=0 echo "vm.swappiness=0">> /etc/sysctl.conf sysctl -p调整系统参数确保系统加载了 br_netfilter 模块。这可以通过运行 lsmod | grep br_netfilter 来检测。如没有加载则运行如下命令加载modprobe br_netfilter在 RHEL/CentOS 7 中：由于 iptables 可能被绕过而导致流量无法正确路由的问题。因此需要确保 在 sysctl 配置中的 net.bridge.bridge-nf-call-iptables 被设置为 1,在sysctl中添加如下配置cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF运行 sysctl --system 生效安装docker从 v1.6.0 版本起，Kubernetes 开始默认允许使用 CRI（容器运行时接口）。从 v1.14.0 版本起，kubeadm 将通过观察已知的 UNIX 域套接字来自动检测 Linux 节点上的容器运行时。如果同时检测到 docker 和 containerd，则优先选择 docker。kubernetes 1.17官方推荐安装 docker 19.03.4 版本，但 1.13.1、17.03、17.06、17.09、18.06 和 18.09 版本也是可以的。安装docker依赖及yum配置工具yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安装dockeryum -y install docker-ce-19.03.4-3.el7修改docker cgroup driver为systemd，以及一些docker的其他设置cat > /etc/docker/daemon.json <<EOF { "graph": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF重启docker并运行 docker info |grep cgroup 验证修改kubernetes 安装配置kubernetes的yum源cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF安装kubeadm、kubelet、kubectlyum -y install kubeadm kubelet kubectlkubernetes初始化打印集群默认初始化配置kubeadm config print init-defaults > k8s-init.yaml编辑得到的k8s-init.yaml配置文件，修改如下项：advertiseAddress，将其修改为master的IP地址。imageRepository，因为k8s.gcr.io在国内不可用，因此，将的值修改为azure中国的镜像k8s.azure.cn/google_containers，否则，kubernetes需要的一些docker镜像拉不下来，kubernetes初始化会一直挂起。etcd相关设置，这里只修改一下etcd本地的存储目录。serviceSubnet子网掩码的范围，这里保持默认。新增配置项podSubnet，在network配置中增加pod的子网范围。修改后的初始化配置如下apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 10.14.230.21 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: k8s-sh-21.vm.90.vc taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /data/k8s/etcd imageRepository: k8s.azk8s.cn/google_containers kind: ClusterConfiguration kubernetesVersion: v1.17.0 networking: dnsDomain: k8s.90.vc serviceSubnet: 10.96.0.0/12 podSubnet: 10.244.0.0/16 scheduler: {}执行kubeadm init --config k8s-init.yaml 进行初始化返回结果如下W0229 21:02:26.431332 41307 validation.go:28] Cannot validate kube-proxy config - no validator is available W0229 21:02:26.431451 41307 validation.go:28] Cannot validate kubelet config - no validator is available [init] Using Kubernetes version: v1.17.0 [preflight] Running pre-flight checks [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Starting the kubelet [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Generating "ca" certificate and key [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [k8s-sh-21.vm.90.vc kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.k8s.90.vc] and IPs [10.96.0.1 10.14.230.21] [certs] Generating "apiserver-kubelet-client" certificate and key [certs] Generating "front-proxy-ca" certificate and key [certs] Generating "front-proxy-client" certificate and key [certs] Generating "etcd/ca" certificate and key [certs] Generating "etcd/server" certificate and key [certs] etcd/server serving cert is signed for DNS names [k8s-sh-21.vm.90.vc localhost] and IPs [10.14.230.21 127.0.0.1 ::1] [certs] Generating "etcd/peer" certificate and key [certs] etcd/peer serving cert is signed for DNS names [k8s-sh-21.vm.90.vc localhost] and IPs [10.14.230.21 127.0.0.1 ::1] [certs] Generating "etcd/healthcheck-client" certificate and key [certs] Generating "apiserver-etcd-client" certificate and key [certs] Generating "sa" key and public key [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "kubelet.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" [control-plane] Creating static Pod manifest for "kube-controller-manager" W0229 21:02:30.970566 41307 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC" [control-plane] Creating static Pod manifest for "kube-scheduler" W0229 21:02:30.971420 41307 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC" [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests" [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s [apiclient] All control plane components are healthy after 33.501703 seconds [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [kubelet] Creating a ConfigMap "kubelet-config-1.17" in namespace kube-system with the configuration for the kubelets in the cluster [upload-certs] Skipping phase. Please see --upload-certs [mark-control-plane] Marking the node k8s-sh-21.vm.90.vc as control-plane by adding the label "node-role.kubernetes.io/master=''" [mark-control-plane] Marking the node k8s-sh-21.vm.90.vc as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule] [bootstrap-token] Using token: abcdef.0123456789abcdef [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace [kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key [addons] Applied essential addon: CoreDNS [addons] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 10.0.2.21:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:8248b6235e0ecf9cb8579dfefce45b6c1d2b3de928cebdf5582621e022f28963 如果执行结果返回Your Kubernetes control-plane has initialized successfully!的话，则说明kubernetes初始化成功。接下来，依据提示，分别进行添加kubectl的配置文件、网络插件、添加其他节点等操作。管理配置文件mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config部署flannel网络插件执行如下操作curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl apply -f kube-flannel.yml返回如下信息podsecuritypolicy.policy/psp.flannel.unprivileged created clusterrole.rbac.authorization.k8s.io/flannel created clusterrolebinding.rbac.authorization.k8s.io/flannel created serviceaccount/flannel created configmap/kube-flannel-cfg created daemonset.apps/kube-flannel-ds-amd64 created daemonset.apps/kube-flannel-ds-arm64 created daemonset.apps/kube-flannel-ds-arm created daemonset.apps/kube-flannel-ds-ppc64le created daemonset.apps/kube-flannel-ds-s390x created这里可能会遇到quay.io无法访问的情况，可以修改kube-flannel文件中的镜像地址，采用国内镜像源获取相关的docker镜像即可。在其余节点上执行如下操作，加入kubernetes集群kubeadm join 10.0.2.21:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:8248b6235e0ecf9cb8579dfefce45b6c1d2b3de928cebdf5582621e022f28963检查kubernetes集群运行状态[root@k8s-sh-21 ~]# kubectl get cs NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":"true"} [root@k8s-sh-21 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8s-sh-21.vm.90.vc Ready master 101m v1.17.3 k8s-sh-22.vm.90.vc Ready <none> 99m v1.17.3 k8s-sh-23.vm.90.vc Ready <none> 99m v1.17.3 [root@k8s-sh-21 ~]# kubectl get pods -A -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system coredns-6cd559f5d5-8vkm8 1/1 Running 0 101m 10.244.0.4 k8s-sh-21.vm.90.vc <none> <none> kube-system coredns-6cd559f5d5-clhrt 1/1 Running 0 101m 10.244.0.3 k8s-sh-21.vm.90.vc <none> <none> kube-system etcd-k8s-sh-21.vm.90.vc 1/1 Running 0 101m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none> kube-system kube-apiserver-k8s-sh-21.vm.90.vc 1/1 Running 0 101m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none> kube-system kube-controller-manager-k8s-sh-21.vm.90.vc 1/1 Running 0 101m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none> kube-system kube-flannel-ds-amd64-6mvlf 1/1 Running 0 100m 10.14.230.23 k8s-sh-23.vm.90.vc <none> <none> kube-system kube-flannel-ds-amd64-dxpgk 1/1 Running 0 100m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none> kube-system kube-flannel-ds-amd64-mjmzz 1/1 Running 0 100m 10.14.230.22 k8s-sh-22.vm.90.vc <none> <none> kube-system kube-proxy-2xtwb 1/1 Running 0 100m 10.14.230.22 k8s-sh-22.vm.90.vc <none> <none> kube-system kube-proxy-fl9bs 1/1 Running 0 101m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none> kube-system kube-proxy-thhn8 1/1 Running 0 100m 10.14.230.23 k8s-sh-23.vm.90.vc <none> <none> kube-system kube-scheduler-k8s-sh-21.vm.90.vc 1/1 Running 0 101m 10.14.230.21 k8s-sh-21.vm.90.vc <none> <none>确保以上node、pod等均为ready和running即可。将kube-proxy改为ipvs模式cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4 编辑configmap中kube-proxy的配置文件。将mode字段修改为ipvskubectl edit cm kube-proxy -n kube-system修改后重启kube-proxykubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'检查修改结果，kube-proxy日志中输出ipvs即表示已经启用ipvs模式，反之则是iptables kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl logs "$1" -n kube-system")}'|grep ProxierHelm的安装及使用部署dashboardingress
Kubernetes CNI网络对比：Flannel、Calico、Canal和Weave
介绍网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求，但在实现方面也具有一定的灵活性。因此，业界已有不少不同的网络方案，来满足特定的环境和要求。CNI意为容器网络接口，它是一种标准的设计，为了让用户在容器创建或销毁时都能够更容易地配置容器网络。在本文中，我们将集中探索与对比目前最流行的CNI插件：Flannel、Calico、Weave和Canal（技术上是多个插件的组合）。这些插件既可以确保满足Kubernetes的网络要求，又能为Kubernetes集群管理员提供他们所需的某些特定的网络功能。背景容器网络是容器选择连接到其他容器、主机和外部网络（如Internet）的机制。容器的runtime提供了各种网络模式，每种模式都会产生不同的体验。例如，Docker默认情况下可以为容器配置以下网络：none：将容器添加到一个容器专门的网络堆栈中，没有对外连接。host：将容器添加到主机的网络堆栈中，没有隔离。default bridge：默认网络模式。每个容器可以通过IP地址相互连接。自定义网桥：用户定义的网桥，具有更多的灵活性、隔离性和其他便利功能。Docker还可以让用户通过其他驱动程序和插件，来配置更高级的网络（包括多主机覆盖网络）。CNI的初衷是创建一个框架，用于在配置或销毁容器时动态配置适当的网络配置和资源。下面链接中的CNI规范概括了用于配制网络的插件接口，这个接口可以让容器运行时与插件进行协调：https://github.com/containernetworking/cni/blob/master/SPEC.md插件负责为接口配置和管理IP地址，并且通常提供与IP管理、每个容器的IP分配、以及多主机连接相关的功能。容器运行时会调用网络插件，从而在容器启动时分配IP地址并配置网络，并在删除容器时再次调用它以清理这些资源。运行时或协调器决定了容器应该加入哪个网络以及它需要调用哪个插件。然后，插件会将接口添加到容器网络命名空间中，作为一个veth对的一侧。接着，它会在主机上进行更改，包括将veth的其他部分连接到网桥。再之后，它会通过调用单独的IPAM（IP地址管理）插件来分配IP地址并设置路由。在Kubernetes中，kubelet可以在适当的时间调用它找到的插件，来为通过kubelet启动的pod进行自动的网络配置。术语在对CNI插件们进行比较之前，我们可以先对网络中会见到的相关术语做一个整体的了解。不论是阅读本文，还是今后接触到其他和CNI有关的内容，了解一些常见术语总是非常有用的。一些最常见的术语包括：第2层网络： OSI（Open Systems Interconnections，开放系统互连）网络模型的“数据链路”层。第2层网络会处理网络上两个相邻节点之间的帧传递。第2层网络的一个值得注意的示例是以太网，其中MAC表示为子层。第3层网络： OSI网络模型的“网络”层。第3层网络的主要关注点，是在第2层连接之上的主机之间路由数据包。IPv4、IPv6和ICMP是第3层网络协议的示例。VXLAN：代表“虚拟可扩展LAN”。首先，VXLAN用于通过在UDP数据报中封装第2层以太网帧来帮助实现大型云部署。VXLAN虚拟化与VLAN类似，但提供更大的灵活性和功能（VLAN仅限于4096个网络ID）。VXLAN是一种封装和覆盖协议，可在现有网络上运行。Overlay网络：Overlay网络是建立在现有网络之上的虚拟逻辑网络。Overlay网络通常用于在现有网络之上提供有用的抽象，并分离和保护不同的逻辑网络。封装：封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在overlay网络中，封装被用于从虚拟网络转换到底层地址空间，从而能路由到不同的位置（数据包可以被解封装，并继续到其目的地）。网状网络：网状网络（Mesh network）是指每个节点连接到许多其他节点以协作路由、并实现更大连接的网络。网状网络允许通过多个路径进行路由，从而提供更可靠的网络。网状网格的缺点是每个附加节点都会增加大量开销。BGP：代表“边界网关协议”，用于管理边缘路由器之间数据包的路由方式。BGP通过考虑可用路径，路由规则和特定网络策略，帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP有时被用作CNI插件中的路由机制，而不是封装的覆盖网络。了解了技术术语和支持各类插件的各种技术之后，下面我们可以开始探索一些最流行的CNI插件了。CNI比较Flannel链接：https://github.com/coreos/flannel由CoreOS开发的项目Flannel，可能是最直接和最受欢迎的CNI插件。它是容器编排系统中最成熟的网络结构示例之一，旨在实现更好的容器间和主机间网络。随着CNI概念的兴起，Flannel CNI插件算是早期的入门。与其他方案相比，Flannel相对容易安装和配置。它被打包为单个二进制文件flanneld，许多常见的Kubernetes集群部署工具和许多Kubernetes发行版都可以默认安装Flannel。Flannel可以使用Kubernetes集群的现有etcd集群来使用API存储其状态信息，因此不需要专用的数据存储。Flannel配置第3层IPv4 overlay网络。它会创建一个大型内部网络，跨越集群中每个节点。在此overlay网络中，每个节点都有一个子网，用于在内部分配IP地址。在配置pod时，每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信，而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中，以便路由到适当的目标。Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN，因为VXLAN性能更良好并且需要的手动干预更少。总的来说，Flannel是大多数用户的不错选择。从管理角度来看，它提供了一个简单的网络模型，用户只需要一些基础知识，就可以设置适合大多数用例的环境。一般来说，在初期使用Flannel是一个稳妥安全的选择，直到你开始需要一些它无法提供的东西。Calico链接：https://github.com/projectcalico/cni-pluginCalico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择，但Calico以其性能、灵活性而闻名。Calico的功能更为全面，不仅提供主机和pod之间的网络连接，还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。在满足系统要求的新配置的Kubernetes集群上，用户可以通过应用单个manifest文件快速部署Calico。如果您对Calico的可选网络策略功能感兴趣，可以向集群应用其他manifest，来启用这些功能。尽管部署Calico所需的操作看起来相当简单，但它创建的网络环境同时具有简单和复杂的属性。与Flannel不同，Calico不使用overlay网络。相反，Calico配置第3层网络，该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时，不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包，而无需额外在流量层中打包流量。除了性能优势之外，在出现网络问题时，用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案，但该过程处理数据包的方式同场难以追踪。使用Calico，标准调试工具可以访问与简单环境中相同的信息，从而使更多开发人员和管理员更容易理解行为。除了网络连接外，Calico还以其先进的网络功能而闻名。 网络策略是其最受追捧的功能之一。此外，Calico还可以与服务网格Istio集成，以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则，描述pod应如何发送和接受流量，提高安全性并控制网络环境。如果对你的环境而言，支持网络策略是非常重要的一点，而且你对其他性能和功能也有需求，那么Calico会是一个理想的选择。此外，如果您现在或未来有可能希望得到技术支持，那么Calico是提供商业支持的。一般来说，当您希望能够长期控制网络，而不是仅仅配置一次并忘记它时，Calico是一个很好的选择。Canal链接：https://github.com/projectcalico/canalCanal也是一个有趣的选择，原因有很多。首先，Canal 是一个项目的名称，它试图将Flannel提供的网络层与Calico的网络策略功能集成在一起。然而，当贡献者完成细节工作时却发现，很明显，如果Flannel和Calico这两个项目的标准化和灵活性都已各自确保了话，那集成也就没那么大必要了。结果，这个官方项目变得有些“烂尾”了，不过却实现了将两种技术部署在一起的预期能力。出于这个原因，即使这个项目不复存在，业界还是会习惯性地将Flannel和Calico的组成称为“Canal”。由于Canal是Flannel和Calico的组合，因此它的优点也在于这两种技术的交叉。网络层用的是Flannel提供的简单overlay，可以在许多不同的部署环境中运行且无需额外的配置。在网络策略方面，Calico强大的网络规则评估，为基础网络提供了更多补充，从而提供了更多的安全性和控制。确保集群满足必要的系统要求（https://docs.projectcalico.org/v3.6/getting-started/kubernetes/requirements）后，用户需要应用两个manifest才能部署Canal，这使得其配置比单独的任何一个项目都困难。如果企业的IT团队计划改变他们的网络方案，且希望在实施改变之前能先对网络策略进行一些实验并获取一些经验，那么Canal是一个不错的选择。一般来说，如果你喜欢Flannel提供的网络模型，但发现Calico的一些功能很诱人，那么不妨尝试一下Canal。从安全角度来看，定义网络策略规则的能力是一个巨大的优势，并且在许多方面是Calico的杀手级功能。能够将该技术应用到熟悉的网络层，意味着您可以获得更强大的环境，且可以省掉大部分的过渡过程。Weave链接：https://www.weave.works/oss/net/Weave是由Weaveworks提供的一种Kubernetes CNI网络选项，它提供的模式和我们目前为止讨论的所有网络方案都不同。Weave在集群中的每个节点之间创建网状overlay网络，参与者之间可以灵活路由。这一特性再结合其他一些独特的功能，在某些可能导致问题的情况下，Weave可以智能地路由。为了创建网络，Weave依赖于网络中每台主机上安装的路由组件。然后，这些路由器交换拓扑信息，以维护可用网络环境的最新视图。当需要将流量发送到位于不同节点上的pod时，Weave路由组件会自动决定是通过“快速数据路径”发送，还是回退到“sleeve”分组转发的方法。快速数据路径依靠内核的本机Open vSwitch数据路径模块，将数据包转发到适当的pod，而无需多次移入和移出用户空间。Weave路由器会更新Open vSwitch配置，以确保内核层具有有关如何路由传入数据包的准确信息。相反，当网络拓扑不适合快速数据路径路由时，sleeve模式可用作备份。它是一种较慢的封装模式，在快速数据路径缺少必要的路由信息或连接的情况下，它可以来路由数据包。当流量通过路由器时，它们会了解哪些对等体与哪些MAC地址相关联，从而允许它们以更少的跳数、更智能地路由后续流量。当网络更改导致可用路由改变时，这一相同的机制可以帮助每个节点进行自行更正。与Calico一样，Weave也为Kubernetes集群提供网络策略功能。设置Weave时，网络策略会自动安装和配置，因此除了添加网络规则之外，用户无需进行其他配置。一个其他网络方案都没有、Weave独有的功能，是对整个网络的简单加密。虽然这会增加相当多的网络开销，但Weave可以使用NaCl加密(http://nacl.cr.yp.to)来为sleeve流量自动加密所有路由流量，而对于快速数据路径流量，因为它需要加密内核中的VXLAN流量，Weave会使用IPsec ESP来加密快速数据路径流量。对于那些寻求功能丰富的网络、同时希望不要增加大量复杂性或管理难度的人来说，Weave是一个很好的选择。它设置起来相对容易，提供了许多内置和自动配置的功能，并且可以在其他解决方案可能出现故障的场景下提供智能路由。网状拓扑结构确实会限制可以合理容纳的网络的大小，不过对于大多数用户来说，这也不是一个大问题。此外，Weave也提供收费的技术支持，可以为企业用户提供故障排除等等技术服务。结语Kubernetes采用的CNI标准，让Kubernetes生态系统中的网络解决方案百花齐放。更多样的选择，意味着大多数用户将能够找到适合其当前需求和部署环境的CNI插件，同时还可以在环境发生变化时也能找到新的解决方案。不同企业之间的运营要求差异很大，因此拥有一系列具有不同复杂程度和功能丰富性的成熟解决方案，大大有助于Kubernetes在满足不同用户独特需求的前提下，仍然能够提供一致的用户体验。[scode type="blue"]本文转载于公众号“RancherLabs”[/scode]
查看所有namespace的pods运行情况kubectl get pods --all-namespaces 查看具体pods，记得后边跟namespace名字哦kubectl get pods kubernetes-dashboard-76479d66bb-nj8wr --namespace=kube-system查看pods具体信息kubectl get pods -o wide kubernetes-dashboard-76479d66bb-nj8wr --namespace=kube-system查看集群健康状态kubectl get cs获取所有deploymentkubectl get deployment --all-namespaces查看kube-system namespace下面的pod/svc/deployment 等等（-o wide 选项可以查看存在哪个对应的节点）kubectl get pod /svc/deployment -n kube-system列出该 namespace 中的所有 pod 包括未初始化的kubectl get pods --include-uninitialized查看deployment()kubectl get deployment nginx-app查看rc和serverskubectl get rc,services查看pods结构信息（重点，通过这个看日志分析错误）对控制器和服务，node同样有效kubectl describe pods xxxxpodsname --namespace=xxxnamespace其他控制器类似吧，就是kubectl get 控制器 控制器具体名称查看pod日志kubectl logs $POD_NAME查看pod变量kubectl exec my-nginx-5j8ok -- printenv | grep SERVICE集群kubectl get cs # 集群健康情况kubectl cluster-info # 集群核心组件运行情况kubectl get namespaces # 表空间名kubectl version # 版本kubectl api-versions # APIkubectl get events # 查看事件kubectl get nodes //获取全部节点kubectl delete node k8s2 //删除节点kubectl rollout status deploy nginx-testkubectl get deployment --all-namespaceskubectl get svc --all-namespaces创建kubectl create -f ./nginx.yaml # 创建资源kubectl apply -f xxx.yaml （创建+更新，可以重复使用）kubectl create -f . # 创建当前目录下的所有yaml资源kubectl create -f ./nginx1.yaml -f ./mysql2.yaml # 使用多个文件创建资源kubectl create -f ./dir # 使用目录下的所有清单文件来创建资源kubectl create -f https://git.io/vPieo # 使用 url 来创建资源kubectl run -i --tty busybox --image=busybox ----创建带有终端的podkubectl run nginx --image=nginx # 启动一个 nginx 实例kubectl run mybusybox --image=busybox --replicas=5 ----启动多个podkubectl explain pods,svc # 获取 pod 和 svc 的文档更新kubectl rolling-update python-v1 -f python-v2.json # 滚动更新 pod frontend-v1kubectl rolling-update python-v1 python-v2 --image=image:v2 # 更新资源名称并更新镜像kubectl rolling-update python --image=image:v2 # 更新 frontend pod 中的镜像kubectl rolling-update python-v1 python-v2 --rollback # 退出已存在的进行中的滚动更新cat pod.json | kubectl replace -f - # 基于 stdin 输入的 JSON 替换 pod为 nginx RC 创建服务，启用本地 80 端口连接到容器上的 8000 端口kubectl expose rc nginx --port=80 --target-port=8000更新单容器 pod 的镜像版本（tag）到 v4kubectl get pod nginx-pod -o yaml | sed 's/(image: myimage):.*$/\1:v4/' | kubectl replace -f -kubectl label pods nginx-pod new-label=awesome # 添加标签kubectl annotate pods nginx-pod icon-url=http://goo.gl/XXBTWq # 添加注解kubectl autoscale deployment foo --min=2 --max=10 # 自动扩展 deployment “foo”编辑资源kubectl edit svc/docker-registry # 编辑名为 docker-registry 的 serviceKUBE_EDITOR="nano" kubectl edit svc/docker-registry # 使用其它编辑器vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf #修改启动参数动态伸缩podkubectl scale --replicas=3 rs/foo # 将foo副本集变成3个kubectl scale --replicas=3 -f foo.yaml # 缩放“foo”中指定的资源。kubectl scale --current-replicas=2 --replicas=3 deployment/mysql # 将deployment/mysql从2个变成3个kubectl scale --replicas=5 rc/foo rc/bar rc/baz # 变更多个控制器的数量kubectl rollout status deploy deployment/mysql # 查看变更进度label 操作kubectl label：添加label值 kubectl label nodes node1 zone=north #增加节点lable值 spec.nodeSelector: zone: north #指定pod在哪个节点kubectl label pod redis-master-1033017107-q47hh role=master #增加lable值 [key]=[value]kubectl label pod redis-master-1033017107-q47hh role- #删除lable值kubectl label pod redis-master-1033017107-q47hh role=backend --overwrite #修改lable值滚动升级kubectl rolling-update：滚动升级 kubectl rolling-update redis-master -f redis-master-controller-v2.yaml #配置文件滚动升级kubectl rolling-update redis-master --image=redis-master:2.0 #命令升级kubectl rolling-update redis-master --image=redis-master:1.0 --rollback #pod版本回滚etcdctl 常用操作etcdctl cluster-health #检查网络集群健康状态etcdctl --endpoints=https://192.168.71.221:2379 cluster-health #带有安全认证检查网络集群健康状态etcdctl member listetcdctl set /k8s/network/config ‘{ “Network”: “10.1.0.0/16” }’etcdctl get /k8s/network/config删除kubectl delete pod -l app=flannel -n kube-system # 根据label删除：kubectl delete -f ./pod.json # 删除 pod.json 文件中定义的类型和名称的 podkubectl delete pod,service baz foo # 删除名为“baz”的 pod 和名为“foo”的 servicekubectl delete pods,services -l name=myLabel # 删除具有 name=myLabel 标签的 pod 和 serivcekubectl delete pods,services -l name=myLabel --include-uninitialized # 删除具有 name=myLabel 标签的 pod 和 service，包括尚未初始化的kubectl -n my-ns delete po,svc --all # 删除 my-ns namespace下的所有 pod 和 serivce，包括尚未初始化的kubectl delete pods prometheus-7fcfcb9f89-qkkf7 --grace-period=0 --force 强制删除kubectl delete deployment kubernetes-dashboard --namespace=kube-systemkubectl delete svc kubernetes-dashboard --namespace=kube-systemkubectl delete -f kubernetes-dashboard.yamlkubectl replace --force -f ./pod.json # 强制替换，删除后重新创建资源。会导致服务中断。交互kubectl logs nginx-pod # dump 输出 pod 的日志（stdout）kubectl logs nginx-pod -c my-container # dump 输出 pod 中容器的日志（stdout，pod 中有多个容器的情况下使用）kubectl logs -f nginx-pod # 流式输出 pod 的日志（stdout）kubectl logs -f nginx-pod -c my-container # 流式输出 pod 中容器的日志（stdout，pod 中有多个容器的情况下使用）kubectl run -i --tty busybox --image=busybox -- sh # 交互式 shell 的方式运行 podkubectl attach nginx-pod -i # 连接到运行中的容器kubectl port-forward nginx-pod 5000:6000 # 转发 pod 中的 6000 端口到本地的 5000 端口kubectl exec nginx-pod -- ls / # 在已存在的容器中执行命令（只有一个容器的情况下）kubectl exec nginx-pod -c my-container -- ls / # 在已存在的容器中执行命令（pod 中有多个容器的情况下）kubectl top pod POD_NAME --containers # 显示指定 pod和容器的指标度量kubectl exec -ti podName /bin/bash # 进入pod调度配置kubectl cordon k8s-node # 标记 my-node 不可调度kubectl drain k8s-node # 清空 my-node 以待维护kubectl uncordon k8s-node # 标记 my-node 可调度kubectl top node k8s-node # 显示 my-node 的指标度量kubectl cluster-info dump # 将当前集群状态输出到 stdout kubectl cluster-info dump --output-directory=/path/to/cluster-state # 将当前集群状态输出到 /path/to/cluster-state如果该键和影响的污点（taint）已存在，则使用指定的值替换kubectl taint nodes foo dedicated=special-user:NoSchedule查看kubelet进程启动参数ps -ef | grep kubelet查看日志:journalctl -u kubelet -f导出配置文件： 导出proxy kubectl get ds -n kube-system -l k8s-app=kube-proxy -o yaml>kube-proxy-ds.yaml 导出kube-dns kubectl get deployment -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-dp.yaml kubectl get services -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-services.yaml 导出所有 configmap kubectl get configmap -n kube-system -o wide -o yaml > configmap.yaml复杂操作命令： 删除kube-system 下Evicted状态的所有pod：kubectl get pods -n kube-system |grep Evicted| awk ‘{print $1}’|xargs kubectl delete pod -n kube-system以下为维护环境相关命令：重启kubelet服务systemctl daemon-reloadsystemctl restart kubelet
kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具，伴随Kubernetes每个版本的发布都会同步更新，kubeadm会对集群配置方面的一些实践做调整，通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。最近发布的Kubernetes 1.15中，kubeadm对HA集群的配置已经达到beta可用，说明kubeadm距离生产环境中可用的距离越来越近了。1.准备1.1系统配置在安装之前，需要先做如下准备。两台CentOS 7.6主机如下：cat /etc/hosts 172.20.0.11 ip-172-20-0-11.cu-sd-cn.vm.7x34.com 172.20.0.12 ip-172-20-0-12.cu-sd-cn.vm.7x34.com 如果各个主机启用了防火墙，需要开放Kubernetes各个组件所需要的端口，可以查看Installing kubeadm中的”Check required ports”一节。 这里简单起见在各节点禁用防火墙：systemctl stop firewalld systemctl disable firewalld禁用SELINUX：setenforce 0 vi /etc/selinux/config SELINUX=disabled创建/etc/sysctl.d/k8s.conf文件，添加如下内容：net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1执行命令使修改生效。modprobe br_netfilter sysctl -p /etc/sysctl.d/k8s.conf1.2kube-proxy开启ipvs的前置条件由于ipvs已经加入到了内核的主干，所以为kube-proxy开启ipvs的前提需要加载以下的内核模块：ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4在所有的Kubernetes节点node1和node2上执行以下脚本:cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4上面脚本创建了的/etc/sysconfig/modules/ipvs.modules文件，保证在节点重启后能自动加载所需模块。 使用lsmod | grep -e ip_vs -e nf_conntrack_ipv4命令查看是否已经正确加载所需的内核模块。接下来还需要确保各个节点上已经安装了ipset软件包yum install ipset。 为了便于查看ipvs的代理规则，最好安装一下管理工具ipvsadm yum install ipvsadm。如果以上前提条件如果不满足，则即使kube-proxy的配置开启了ipvs模式，也会退回到iptables模式。1.3安装DockerKubernetes从1.6开始使用CRI(Container Runtime Interface)容器运行时接口。默认的容器运行时仍然是Docker，使用的是kubelet中内置dockershim CRI实现。安装docker的yum源:yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo查看最新的Docker版本：yum list docker-ce.x86_64 --showduplicates |sort -r docker-ce.x86_64 3:18.09.7-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.6-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.5-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.4-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.3-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.2-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable docker-ce.x86_64 18.06.3.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.2.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable ...Kubernetes 1.15当前支持的docker版本列表是1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09。 这里在各节点安装docker的18.09.7版本。yum makecache fast yum install -y --setopt=obsoletes=0 \ docker-ce-18.09.7-3.el7 systemctl start docker systemctl enable docker确认一下iptables filter表中FOWARD链的默认策略(pllicy)为ACCEPT。iptables -nvL Chain INPUT (policy ACCEPT 263 packets, 19209 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/01.4 修改docker cgroup driver为systemd根据文档CRI installation中的内容，对于使用systemd作为init system的Linux的发行版，使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定，因此这里修改各个节点上docker的cgroup driver为systemd。创建或修改/etc/docker/daemon.json：{ "exec-opts": ["native.cgroupdriver=systemd"] }重启docker：systemctl restart docker docker info | grep Cgroup Cgroup Driver: systemd2.使用kubeadm部署Kubernetes2.1 安装kubeadm和kubelet下面在各节点安装kubeadm和kubelet：cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF安装kubeadm、kubectl、kubeletyum makecache fast yum install -y kubelet kubeadm kubectl ... Installed: kubeadm.x86_64 0:1.15.0-0 kubectl.x86_64 0:1.15.0-0 kubelet.x86_64 0:1.15.0-0 Dependency Installed: conntrack-tools.x86_64 0:1.4.4-4.el7 cri-tools.x86_64 0:1.12.0-0 kubernetes-cni.x86_64 0:0.7.5-0 libnetfilter_cthelper.x86_64 0:1.0.0-9.el7 libnetfilter_cttimeout.x86_64 0:1.0.0-6.el7 libnetfilter_queue.x86_64 0:1.0.2-2.el7_2 socat.x86_64 0:1.7.3.2-2.el7 从安装结果可以看出还安装了cri-tools, kubernetes-cni, socat三个依赖：官方从Kubernetes 1.14开始将cni依赖升级到了0.7.5版本socat是kubelet的依赖cri-tools是CRI(Container Runtime Interface)容器运行时接口的命令行工具运行kubelet --help可以看到原来kubelet的绝大多数命令行flag参数都被DEPRECATED了，如：...... --address 0.0.0.0 The IP address for the Kubelet to serve on (set to 0.0.0.0 for all IPv4 interfaces and `::` for all IPv6 interfaces) (default 0.0.0.0) (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.) ......而官方推荐我们使用--config指定配置文件，并在配置文件中指定原来这些flag所配置的内容。具体内容可以查看这里Set Kubelet parameters via a config file。这也是Kubernetes为了支持动态Kubelet配置（Dynamic Kubelet Configuration）才这么做的，参考Reconfigure a Node’s Kubelet in a Live Cluster。kubelet的配置文件必须是json或yaml格式，具体可查看这里。Kubernetes 1.8开始要求关闭系统的Swap，如果不关闭，默认配置下kubelet将无法启动。 关闭系统的Swap方法如下:swapoff -a修改 /etc/fstab 文件，注释掉 SWAP 的自动挂载，使用free -m确认swap已经关闭。 swappiness参数调整，修改/etc/sysctl.d/k8s.conf添加下面一行：vm.swappiness=0执行sysctl -p /etc/sysctl.d/k8s.conf使修改生效。因为这里本次用于测试两台主机上还运行其他服务，关闭swap可能会对其他服务产生影响，所以这里修改kubelet的配置去掉这个限制。 使用kubelet的启动参数--fail-swap-on=false去掉必须关闭Swap的限制，修改/etc/sysconfig/kubelet，加入：KUBELET_EXTRA_ARGS=--fail-swap-on=false2.2 使用kubeadm init初始化集群在各节点开机启动kubelet服务：systemctl enable kubelet.service使用kubeadm config print init-defaults可以打印集群初始化默认的使用的配置：apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 1.2.3.4 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: node1 taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.14.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 scheduler: {} 从默认的配置中可以看到，可以使用imageRepository定制在集群初始化时拉取k8s所需镜像的地址。基于默认配置定制出本次使用kubeadm初始化集群所需的配置文件kubeadm.yaml：apiVersion: kubeadm.k8s.io/v1beta2 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.99.11 bindPort: 6443 nodeRegistration: taints: - effect: PreferNoSchedule key: node-role.kubernetes.io/master --- apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration kubernetesVersion: v1.15.0 networking: podSubnet: 10.244.0.0/16使用kubeadm默认配置初始化的集群，会在master节点打上node-role.kubernetes.io/master:NoSchedule的污点，阻止master节点接受调度运行工作负载。这里测试环境只有两个节点，所以将这个taint修改为node-role.kubernetes.io/master:PreferNoSchedule。在开始初始化集群之前可以使用kubeadm config images pull预先在各个节点上拉取所k8s需要的docker镜像。接下来使用kubeadm初始化集群，选择node1作为Master Node，在node1上执行下面的命令：kubeadm init --config kubeadm.yaml --ignore-preflight-errors=Swap [init] Using Kubernetes version: v1.15.0 [preflight] Running pre-flight checks [WARNING Swap]: running with swap on is not supported. Please disable swap [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Activating the kubelet service [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Generating "etcd/ca" certificate and key [certs] Generating "apiserver-etcd-client" certificate and key [certs] Generating "etcd/server" certificate and key [certs] etcd/server serving cert is signed for DNS names [node1 localhost] and IPs [192.168.99.11 127.0.0.1 ::1] [certs] Generating "etcd/peer" certificate and key [certs] etcd/peer serving cert is signed for DNS names [node1 localhost] and IPs [192.168.99.11 127.0.0.1 ::1] [certs] Generating "etcd/healthcheck-client" certificate and key [certs] Generating "ca" certificate and key [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [node1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.99.11] [certs] Generating "apiserver-kubelet-client" certificate and key [certs] Generating "front-proxy-ca" certificate and key [certs] Generating "front-proxy-client" certificate and key [certs] Generating "sa" key and public key [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "kubelet.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" [control-plane] Creating static Pod manifest for "kube-controller-manager" [control-plane] Creating static Pod manifest for "kube-scheduler" [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests" [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s [apiclient] All control plane components are healthy after 26.004907 seconds [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [kubelet] Creating a ConfigMap "kubelet-config-1.15" in namespace kube-system with the configuration for the kubelets in the cluster [upload-certs] Skipping phase. Please see --upload-certs [mark-control-plane] Marking the node node1 as control-plane by adding the label "node-role.kubernetes.io/master=''" [mark-control-plane] Marking the node node1 as control-plane by adding the taints [node-role.kubernetes.io/master:PreferNoSchedule] [bootstrap-token] Using token: 4qcl2f.gtl3h8e5kjltuo0r [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace [addons] Applied essential addon: CoreDNS [addons] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.99.11:6443 --token 4qcl2f.gtl3h8e5kjltuo0r \ --discovery-token-ca-cert-hash sha256:7ed5404175cc0bf18dbfe53f19d4a35b1e3d40c19b10924275868ebf2a3bbe6e 上面记录了完成的初始化输出的内容，根据输出的内容基本上可以看出手动初始化安装一个Kubernetes集群所需要的关键步骤。 其中有以下关键内容：[kubelet-start] 生成kubelet的配置文件”/var/lib/kubelet/config.yaml”[certs]生成相关的各种证书[kubeconfig]生成相关的kubeconfig文件[control-plane]使用/etc/kubernetes/manifests目录中的yaml文件创建apiserver、controller-manager、scheduler的静态pod[bootstraptoken]生成token记录下来，后边使用kubeadm join往集群中添加节点时会用到下面的命令是配置常规用户如何使用kubectl访问集群：mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config最后给出了将节点加入集群的命令kubeadm join 192.168.99.11:6443 --token 4qcl2f.gtl3h8e5kjltuo0r \ --discovery-token-ca-cert-hash sha256:7ed5404175cc0bf18dbfe53f19d4a35b1e3d40c19b10924275868ebf2a3bbe6e查看一下集群状态，确认个组件都处于healthy状态：kubectl get cs NAME STATUS MESSAGE ERROR controller-manager Healthy ok scheduler Healthy ok etcd-0 Healthy {"health":"true"} 集群初始化如果遇到问题，可以使用下面的命令进行清理：kubeadm reset ifconfig cni0 down ip link delete cni0 ifconfig flannel.1 down ip link delete flannel.1 rm -rf /var/lib/cni/2.3 安装Pod Network接下来安装flannel network add-on：mkdir -p ~/k8s/ cd ~/k8s curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl apply -f kube-flannel.yml clusterrole.rbac.authorization.k8s.io/flannel created clusterrolebinding.rbac.authorization.k8s.io/flannel created serviceaccount/flannel created configmap/kube-flannel-cfg created daemonset.extensions/kube-flannel-ds-amd64 created daemonset.extensions/kube-flannel-ds-arm64 created daemonset.extensions/kube-flannel-ds-arm created daemonset.extensions/kube-flannel-ds-ppc64le created daemonset.extensions/kube-flannel-ds-s390x created这里注意kube-flannel.yml这个文件里的flannel的镜像是0.11.0，quay.io/coreos/flannel:v0.11.0-amd64如果Node有多个网卡的话，参考flannel issues 39701，目前需要在kube-flannel.yml中使用--iface参数指定集群主机内网网卡的名称，否则可能会出现dns无法解析。需要将kube-flannel.yml下载到本地，flanneld启动参数加上--iface=<iface-name>...... containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.11.0-amd64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr - --iface=eth1 ......使用kubectl get pod --all-namespaces -o wide确保所有的Pod都处于Running状态。kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-5c98db65d4-dr8lf 1/1 Running 0 52m coredns-5c98db65d4-lp8dg 1/1 Running 0 52m etcd-node1 1/1 Running 0 51m kube-apiserver-node1 1/1 Running 0 51m kube-controller-manager-node1 1/1 Running 0 51m kube-flannel-ds-amd64-mm296 1/1 Running 0 44s kube-proxy-kchkf 1/1 Running 0 52m kube-scheduler-node1 1/1 Running 0 51m2.4 测试集群DNS是否可用kubectl run curl --image=radial/busyboxplus:curl -it kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead. If you don't see a command prompt, try pressing enter. [ root@curl-5cc7b478b6-r997p:/ ]$ 进入后执行nslookup kubernetes.default确认解析正常:nslookup kubernetes.default Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes.default Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local2.5 向Kubernetes集群中添加Node节点下面将node2这个主机添加到Kubernetes集群中，在node2上执行:kubeadm join 192.168.99.11:6443 --token 4qcl2f.gtl3h8e5kjltuo0r \ --discovery-token-ca-cert-hash sha256:7ed5404175cc0bf18dbfe53f19d4a35b1e3d40c19b10924275868ebf2a3bbe6e \ --ignore-preflight-errors=Swap [preflight] Running pre-flight checks [WARNING Swap]: running with swap on is not supported. Please disable swap [WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service' [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.15" ConfigMap in the kube-system namespace [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Activating the kubelet service [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap... This node has joined the cluster: * Certificate signing request was sent to apiserver and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.node2加入集群很是顺利，下面在master节点上执行命令查看集群中的节点：kubectl get node NAME STATUS ROLES AGE VERSION node1 Ready master 57m v1.15.0 node2 Ready <none> 11s v1.15.02.5.1 如何从集群中移除Node如果需要从集群中移除node2这个Node执行下面的命令：在master节点上执行：kubectl drain node2 --delete-local-data --force --ignore-daemonsets kubectl delete node node2在node2上执行：kubeadm reset ifconfig cni0 down ip link delete cni0 ifconfig flannel.1 down ip link delete flannel.1 rm -rf /var/lib/cni/在node1上执行：kubectl delete node node22.6 kube-proxy开启ipvs修改ConfigMap的kube-system/kube-proxy中的config.conf，mode: "ipvs"：kubectl edit cm kube-proxy -n kube-system之后重启各个节点上的kube-proxy pod：kubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'kubectl get pod -n kube-system | grep kube-proxy kube-proxy-7fsrg 1/1 Running 0 3s kube-proxy-k8vhm 1/1 Running 0 9s kubectl logs kube-proxy-7fsrg -n kube-system I0703 04:42:33.308289 1 server_others.go:170] Using ipvs Proxier. W0703 04:42:33.309074 1 proxier.go:401] IPVS scheduler not specified, use rr by default I0703 04:42:33.309831 1 server.go:534] Version: v1.15.0 I0703 04:42:33.320088 1 conntrack.go:52] Setting nf_conntrack_max to 131072 I0703 04:42:33.320365 1 config.go:96] Starting endpoints config controller I0703 04:42:33.320393 1 controller_utils.go:1029] Waiting for caches to sync for endpoints config controller I0703 04:42:33.320455 1 config.go:187] Starting service config controller I0703 04:42:33.320470 1 controller_utils.go:1029] Waiting for caches to sync for service config controller I0703 04:42:33.420899 1 controller_utils.go:1036] Caches are synced for endpoints config controller I0703 04:42:33.420969 1 controller_utils.go:1036] Caches are synced for service config controller日志中打印出了Using ipvs Proxier，说明ipvs模式已经开启。3.Kubernetes常用组件部署越来越多的公司和团队开始使用Helm这个Kubernetes的包管理器，这里也将使用Helm安装Kubernetes的常用组件。3.1 Helm的安装Helm由客户端命helm令行工具和服务端tiller组成，Helm的安装十分简单。 下载helm命令行工具到master节点node1的/usr/local/bin下，这里下载的2.14.1版本：curl -O https://get.helm.sh/helm-v2.14.1-linux-amd64.tar.gz tar -zxvf helm-v2.14.1-linux-amd64.tar.gz cd linux-amd64/ cp helm /usr/local/bin/为了安装服务端tiller，还需要在这台机器上配置好kubectl工具和kubeconfig文件，确保kubectl工具可以在这台机器上访问apiserver且正常使用。 这里的node1节点已经配置好了kubectl。因为Kubernetes APIServer开启了RBAC访问控制，所以需要创建tiller使用的service account: tiller并分配合适的角色给它。 详细内容可以查看helm文档中的Role-based Access Control。 这里简单起见直接分配cluster-admin这个集群内置的ClusterRole给它。创建helm-rbac.yaml文件：apiVersion: v1 kind: ServiceAccount metadata: name: tiller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: tiller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller namespace: kube-systemubectl create -f helm-rbac.yaml serviceaccount/tiller created clusterrolebinding.rbac.authorization.k8s.io/tiller created接下来使用helm部署tiller:helm init --service-account tiller --skip-refresh Creating /root/.helm Creating /root/.helm/repository Creating /root/.helm/repository/cache Creating /root/.helm/repository/local Creating /root/.helm/plugins Creating /root/.helm/starters Creating /root/.helm/cache/archive Creating /root/.helm/repository/repositories.yaml Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com Adding local repo with URL: http://127.0.0.1:8879/charts $HELM_HOME has been configured at /root/.helm. Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster. Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy. To prevent this, run `helm init` with the --tiller-tls-verify flag. For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation Happy Helming!tiller默认被部署在k8s集群中的kube-system这个namespace下：kubectl get pod -n kube-system -l app=helm NAME READY STATUS RESTARTS AGE tiller-deploy-c4fd4cd68-dwkhv 1/1 Running 0 83shelm version Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}注意由于某些原因需要网络可以访问gcr.io和kubernetes-charts.storage.googleapis.com，如果无法访问可以通过helm init --service-account tiller --tiller-image <your-docker-registry>/tiller:v2.13.1 --skip-refresh使用私有镜像仓库中的tiller镜像最后在node1上修改helm chart仓库的地址为azure提供的镜像地址：helm repo add stable http://mirror.azure.cn/kubernetes/charts "stable" has been added to your repositories helm repo list NAME URL stable http://mirror.azure.cn/kubernetes/charts local http://127.0.0.1:8879/charts 3.2 使用Helm部署Nginx Ingress为了便于将集群中的服务暴露到集群外部，需要使用Ingress。接下来使用Helm将Nginx Ingress部署到Kubernetes上。 Nginx Ingress Controller被部署在Kubernetes的边缘节点上，关于Kubernetes边缘节点的高可用相关的内容可以查看之前整理的Bare metal环境下Kubernetes Ingress边缘节点的高可用,Ingress Controller使用hostNetwork。我们将node1(192.168.99.11)做为边缘节点，打上Label：kubectl label node node1 node-role.kubernetes.io/edge= node/node1 labeled kubectl get node NAME STATUS ROLES AGE VERSION node1 Ready edge,master 138m v1.15.0 node2 Ready <none> 82m v1.15.0stable/nginx-ingress chart的值文件ingress-nginx.yaml如下：controller: replicaCount: 1 hostNetwork: true nodeSelector: node-role.kubernetes.io/edge: '' affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx-ingress - key: component operator: In values: - controller topologyKey: kubernetes.io/hostname tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: PreferNoSchedule defaultBackend: nodeSelector: node-role.kubernetes.io/edge: '' tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: PreferNoSchedulenginx ingress controller的副本数replicaCount为1，将被调度到node1这个边缘节点上。这里并没有指定nginx ingress controller service的externalIPs，而是通过hostNetwork: true设置nginx ingress controller使用宿主机网络。helm repo update helm install stable/nginx-ingress \ -n nginx-ingress \ --namespace ingress-nginx \ -f ingress-nginx.yamlkubectl get pod -n ingress-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-ingress-controller-cc9b6d55b-pr8vr 1/1 Running 0 10m 192.168.99.11 node1 <none> <none> nginx-ingress-default-backend-cc888fd56-bf4h2 1/1 Running 0 10m 10.244.0.14 node1 <none> <none>如果访问http://192.168.99.11返回default backend，则部署完成。3.3 使用Helm部署dashboardkubernetes-dashboard.yaml：image: repository: k8s.gcr.io/kubernetes-dashboard-amd64 tag: v1.10.1 ingress: enabled: true hosts: - k8s.frognew.com annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" tls: - secretName: frognew-com-tls-secret hosts: - k8s.frognew.com nodeSelector: node-role.kubernetes.io/edge: '' tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: PreferNoSchedule rbac: clusterAdminRole: truehelm install stable/kubernetes-dashboard \ -n kubernetes-dashboard \ --namespace kube-system \ -f kubernetes-dashboard.yamlkubectl -n kube-system get secret | grep kubernetes-dashboard-token kubernetes-dashboard-token-pkm2s kubernetes.io/service-account-token 3 3m7s kubectl describe -n kube-system secret/kubernetes-dashboard-token-pkm2s Name: kubernetes-dashboard-token-pkm2s Namespace: kube-system Labels: <none> Annotations: kubernetes.io/service-account.name: kubernetes-dashboard kubernetes.io/service-account.uid: 2f0781dd-156a-11e9-b0f0-080027bb7c43 Type: kubernetes.io/service-account-token Data ==== ca.crt: 1025 bytes namespace: 11 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.[binary].24ad6ZgZMxdydpwlmYAiMxZ9VSIN7dDR7Q6-RLW0qC81ajXoQKHAyrEGpIonfld3gqbE0xO8nisskpmlkQra72-9X6sBPoByqIKyTsO83BQlME2sfOJemWD0HqzwSCjvSQa0x-bUlq9HgH2vEXzpFuSS6Svi7RbfzLXlEuggNoC4MfA4E2hF1OX_ml8iAKx-49y1BQQe5FGWyCyBSi1TD_-ZpVs44H5gIvsGK2kcvi0JT4oHXtWjjQBKLIWL7xxyRCSE4HmUZT2StIHnOwlX7IEIB0oBX4mPg2_xNGnqwcu-8OERU9IoqAAE2cZa0v3b5O2LMcJPrcxrVOukvRIumA在dashboard的登录窗口使用上面的token登录。3.4 使用Helm部署metrics-server从Heapster的github https://github.com/kubernetes/heapster中可以看到已经，heapster已经DEPRECATED。 这里是heapster的deprecation timeline。 可以看出heapster从Kubernetes 1.12开始从Kubernetes各种安装脚本中移除。Kubernetes推荐使用metrics-server。我们这里也使用helm来部署metrics-server。metrics-server.yaml:args: - --logtostderr - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP nodeSelector: node-role.kubernetes.io/edge: '' tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: PreferNoSchedulehelm install stable/metrics-server \ -n metrics-server \ --namespace kube-system \ -f metrics-server.yaml使用下面的命令可以获取到关于集群节点基本的指标信息：kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% node1 650m 32% 1276Mi 73% node2 73m 3% 527Mi 30% Codekubectl top pod -n kube-system NAME CPU(cores) MEMORY(bytes) coredns-5c98db65d4-dr8lf 8m 7Mi coredns-5c98db65d4-lp8dg 6m 8Mi etcd-node1 44m 46Mi kube-apiserver-node1 74m 295Mi kube-controller-manager-node1 35m 50Mi kube-flannel-ds-amd64-7lwm9 2m 8Mi kube-flannel-ds-amd64-mm296 5m 9Mi kube-proxy-7fsrg 1m 11Mi kube-proxy-k8vhm 3m 11Mi kube-scheduler-node1 8m 15Mi kubernetes-dashboard-848b8dd798-c4sc2 2m 14Mi metrics-server-8456fb6676-fwh2t 10m 19Mi tiller-deploy-7bf78cdbf7-9q94c 1m 16Mi 遗憾的是，当前Kubernetes Dashboard还不支持metrics-server。因此如果使用metrics-server替代了heapster，将无法在dashboard中以图形展示Pod的内存和CPU情况(实际上这也不是很重要，当前我们是在Prometheus和Grafana中定制的Kubernetes集群中各个Pod的监控，因此在dashboard中查看Pod内存和CPU也不是很重要)。 Dashboard的github上有很多这方面的讨论，如https://github.com/kubernetes/dashboard/issues/2986，Dashboard已经准备在将来的某个时间点支持metrics-server。但由于metrics-server和metrics pipeline肯定是Kubernetes在monitor方面未来的方向，所以推荐使用metrics-server。4.总结本次安装涉及到的Docker镜像：# network and dns quay.io/coreos/flannel:v0.11.0-amd64 k8s.gcr.io/coredns:1.3.1 # helm and tiller gcr.io/kubernetes-helm/tiller:v2.14.1 # nginx ingress quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1 k8s.gcr.io/defaultbackend:1.5 # dashboard and metric-sever k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 gcr.io/google_containers/metrics-server-amd64:v0.3.2参考Installing kubeadmUsing kubeadm to Create a ClusterGet Docker CE for CentOSkubernetes: k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2