kubernetes是一种容器管理开源项目,用于管理容器化的工作负载和服务,可促进声明式配置和自动化,支持容器自身的不足。

  • 解决了容器安全问题:密钥与配置管理
  • 容器管理:部署,升级回滚,扩缩容,自愈等。
  • 网络问题:服务发现和负载均衡

组件和概念

Kubernetes主要由以下几个核心组件组成:

master

  • apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;可以说是k8s的内部交互的网关总线。
  • controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;是控制器的管理者,负责很多的控制器。
  • scheduler负责资源的调度,按照(预选优选)调度策略将Pod调度到相应的机器上;

node

  • kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;主要干活的对象,负责和docker进行交互,创建容器,维护容器。
  • kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;提供了一种网络模式。
  • docker engine docker引擎,负责docker的创建和管理,随着cri的发展,不同容器运行时的接入,docker迟早是要重kubelet中出去的,目前开源的containerd对于大家来说是一个不错的选择。

网络

  • fannel实现pod网络的互通

数据库

  • etcd保存了整个集群的状态;实现持久化数据的k-vdb

重要概念

  • namespaces:命名空间,主要是实现资源的隔离,Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。比如我们将namespace命名为系统名,一个系统一个namespace。
  • pod: 一种应用的实例,例如一个web站点,包含前端,后端,数据库这三个容器,放在一个pod中对外就是一个web服务。
  • service:pod的路由代理的抽象,集群内通过service提供的固定地址进行交互,而service来做服务发现和负载均衡,来和变化的pod进行交互。
  • ingress:类似于nginx的转发功能,暴露出service的地址来对外暴露服务。

上面是最基本要了解的资源概念,还有很多核心概念

安装部署

安装包

源码编译二进制文件

1、You have a working [Go environment].

$ go get -d k8s.io/kubernetes
$ cd $GOPATH/src/k8s.io/kubernetes
$ make

2、You have a working [Docker environment].

$ git clone https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ make quick-release

直接下载

官方提供了直接下载的路径https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md

rpm

打rpm包,直接工程下载工程

https://github.com/kubernetes/release

将上面编译好的文件可执行文件复制到这个项目的rpm目录下

修改这个目录下的spec文件,比如版本信息,使用二进制文件为本地文件,也就是上面穿过来的,而不是去网上下载

再下载一些基础镜像

最后直接执行当前目录下的./docker-build.sh就可以自己启动镜像编译成对应的rpm文件

对应执行的基本过程

yum源

最后提供一个k8s的yum源

[virt7-testing]
name=virt7-testing
baseurl=http://cbs.centos.org/repos/virt7-testing/x86_64/os/
gpgcheck=0

总结

可见,能上网直接yum源,不能上网,就是直接下载二进制文件

单例

就是在一台机器上部署一个k8s集群,可以下载后一个个组件镜像然后在k8s启动,我们这边推荐k8s官方推出的minikube工具来部署,一般给我们正常做开发测试使用是足够的。

minikube

Kubernetes 集群的搭建是有一定难度的,尤其是对于初学者来说,好多概念和原理不懂,即使有现成的教程也会出现很多不可预知的问题,很容易打击学习的积极性,就此弃坑。好在 Kubernetes 社区提供了可以在本地开发和体验的极简集群安装 MiniKube,对于入门学习来说很方便。

MiniKube其实就是把k8s的几个组件的镜像下载下来,然后使用docker进行启动,当然设置了启动参数 ,在一台机器上启动了所有的组件然后就是一个单节点的k8s集群,所以说minikube就是一个部署工具,和k8s集群本身没有关系,将k8s集群运行在docker中,不想我们直接运行在物理机上,但是在国内由于网络访问原因(懂的),即使有梯子也很折腾,所以需要修改源为阿里的后MiniKube 安装。使用阿里修改后的 MiniKube 就可以从阿里云的镜像地址来获取所需 Docker 镜像和配置,其它的并没有差异。

minikube本身就提供了可执行的二进制文件,可以直接下载,用命令行启动,就能自动的将k8s部署好

前置工作

1、vm

首先macOS是否支持虚拟化,在终端上运行命令

sysctl -a | grep -E --color 'machdep.cpu.features|VMX'

如果尚未安装管理程序,请立即安装以下之一:

1、HyperKit
2、VirtualBox
3、VMware Fusion

因为minikube是运行在一个本地的VM上的,而不是运行在本地,所以需要vm。

2、docker已经安装

安装包

我们以macos为例

macOS 安装 Minikube 最简单的方法是使用 Homebrew:

brew install minikube

你也可以通过下载单节点二进制文件进行安装:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 \
&& chmod +x minikube

这是一个简单的将 Minikube 可执行文件添加至 path 的方法:

sudo mv minikube /usr/local/bin

清理本地状态

如果您之前安装过 Minikube,并运行了:

minikube start

并且 minikube start 返回了一个错误:

machine does not exist

那么,你需要清理 minikube 的本地状态:

minikube delete

使用minikube安装k8s

使用minikube安装k8s集群十分简单,一条命令就可以,minikube会去创建一个vm虚拟机,然后在机器上部署docker,k8s集群,完成内部的基本设置。

minikube start --image-mirror-country='cn' --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers' --cache-images=true --vm-driver=virtualbox --kubernetes-version=1.14.10

启动参数

--vm-driver=*** 从1.5.0版本开始,Minikube缺省使用本地最好的驱动来创建Kubernetes本地环境。

    Minikube在不同操作系统上支持不同的驱动

    macOS:xhyve driver 缺省驱动, VirtualBox 或 VMware Fusion
    Linux: VirtualBox 或 KVM2
    Windows:VirtualBox 或 Hyper-V

--image-mirror-country='cn'
--image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'
将缺省利用 registry.cn-hangzhou.aliyuncs.com/google_containers 作为安装Kubernetes的容器镜像仓库 (阿里云版本可选)

--iso-url=*** 利用阿里云的镜像地址下载相应的 .iso 文件 (阿里云版本可选)
--registry-mirror=***为了拉取Docker Hub镜像,需要为 Docker daemon 配置镜像加速,参考阿里云镜像服务
--cpus=2: 为minikube虚拟机分配CPU核数
--memory=2048mb: 为minikube虚拟机分配内存数
--kubernetes-version=***: minikube 虚拟机将使用的 kubernetes 版本

//设置docker环境变量,这个是代理,一般不需要设置。
–docker-env HTTP_PROXY=http://proxy.sha.sap.corp:8080/
–docker-env HTTPS_PROXY=http://proxy.sha.sap.corp:8080/

运行结果如下

$ minikube start --image-mirror-country='cn' --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers' --cache-images=true --vm-driver=virtualbox --kubernetes-version=1.18.3
😄  minikube v1.11.0 on Darwin 10.15.2
✨  Using the virtualbox driver based on user configuration
✅  Using image repository registry.cn-hangzhou.aliyuncs.com/google_containers
👍  Starting control plane node minikube in cluster minikube
🔥  Creating virtualbox VM (CPUs=2, Memory=4000MB, Disk=20000MB) ...
🌐  Found network options:
    ▪ HTTP_PROXY=http://127.0.0.1:6666
❗  You appear to be using a proxy, but your NO_PROXY environment does not include the minikube IP (192.168.99.107).
📘  Please see https://minikube.sigs.k8s.io/docs/handbook/vpn_and_proxy/ for more details
    ▪ HTTPS_PROXY=http://127.0.0.1:6666
❗  This VM is having trouble accessing https://registry.cn-hangzhou.aliyuncs.com/google_containers
💡  To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
🐳  Preparing Kubernetes v1.18.3 on Docker 19.03.8 ...
    ▪ env HTTP_PROXY=http://127.0.0.1:6666
    ▪ env HTTPS_PROXY=http://127.0.0.1:6666
^@🔎  Verifying Kubernetes components...
🌟  Enabled addons: default-storageclass, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube"

❗  /usr/local/bin/kubectl is version 1.20.2, which may be incompatible with Kubernetes 1.18.3.
💡  You can also use 'minikube kubectl -- get pods' to invoke a matching version

可以看到使用vmbox创建了一个虚拟机,然后在虚拟机中运行了k8s,我们下面会进入虚拟机查看对应的进程。我们先来看一下,对应的配置文件

$ cat .kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ~/.minikube/ca.crt
    server: https://192.168.99.107:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: ~/.minikube/profiles/minikube/client.crt
    client-key: ~/.minikube/profiles/minikube/client.key

可以看到minikube start自动创建一个minikube的context,我们kubectl就是使用的这个配置,我们可以看到对应的证书都是在~/.minikube,我们看一下这个目录

.minikube $ ll
total 64
drwxr-xr-x  2 chunyinjiang  staff    64 Aug  9 09:49 addons
-rw-r--r--  1 chunyinjiang  staff  1066 Aug  9 10:24 ca.crt
-rw-------  1 chunyinjiang  staff  1679 Aug  9 10:24 ca.key
-rwxr-xr-x  1 chunyinjiang  staff  1054 Aug  9 10:45 ca.pem
drwxr-xr-x  6 chunyinjiang  staff   192 Aug  9 10:47 cache
-rwxr-xr-x  1 chunyinjiang  staff  1094 Aug  9 10:45 cert.pem
drwxr-xr-x  6 chunyinjiang  staff   192 Aug  9 10:05 certs
drwxr-xr-x  3 chunyinjiang  staff    96 Aug  9 10:44 config
drwxr-xr-x  2 chunyinjiang  staff    64 Aug  9 09:49 files
-rwxr-xr-x  1 chunyinjiang  staff  1675 Aug  9 10:45 key.pem
-rw-r--r--  1 chunyinjiang  staff    29 Aug  9 09:50 last_update_check
drwxr-xr-x  2 chunyinjiang  staff    64 Aug  9 09:49 logs
drwxr-xr-x  5 chunyinjiang  staff   160 Aug  9 10:45 machines
drwx------  3 chunyinjiang  staff    96 Aug  9 10:45 profiles
-rw-r--r--  1 chunyinjiang  staff  1074 Aug  9 10:24 proxy-client-ca.crt
-rw-------  1 chunyinjiang  staff  1675 Aug  9 10:24 proxy-client-ca.key

简单的可以看出minikube相关文件都在这里,后面有需要深入研究的在看。

安装kubectl

minikube只是在创建的虚拟机minikube中安装了k8s集群和相关组件,我们还需要在本地去安装管理工具kubectl来管理这个虚拟机中的集群。

我是macOS 系统并使用 Homebrew 包管理器,通过 Homebrew 安装 kubectl。

运行安装命令:

    brew install kubernetes-cli

测试以确保您安装的版本是最新的:

MacBook-Pro:minikube chunyinjiang$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-21T14:51:23Z", GoVersion:"go1.14.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:43:34Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

当然也可以下载二进制文件进行安装,下面有kubectl的具体说明。

检查 kubectl 的配置

通过获取集群状态检查 kubectl 是否被正确配置:

kubectl cluster-info

如果您看到一个 URL 被返回,那么 kubectl 已经被正确配置,能够正常访问您的 Kubernetes 集群。

如果您看到类似以下的信息被返回,那么 kubectl 没有被正确配置,无法正常访问您的 Kubernetes 集群。

The connection to the server <server-name:port> was refused - did you specify the right host or port?

如果 kubectl cluster-info 能够返回 url 响应,但您无法访问您的集群,可以使用下面的命令检查配置是否正确:

kubectl cluster-info dump

至于kubectl的具体使用包括自动补全功能,下面会详细说明。

查看集群状态

MacBook-Pro:minikube chunyinjiang$ kubectl get pod --all-namespaces -o wide
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
kube-system   coredns-546565776c-dcvb4           1/1     Running   0          10m   172.17.0.3       minikube   <none>           <none>
kube-system   coredns-546565776c-m9qlc           1/1     Running   0          10m   172.17.0.2       minikube   <none>           <none>
kube-system   etcd-minikube                      1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
kube-system   kube-apiserver-minikube            1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
kube-system   kube-controller-manager-minikube   1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
kube-system   kube-proxy-hw2qb                   1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
kube-system   kube-scheduler-minikube            1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
kube-system   storage-provisioner                1/1     Running   0          10m   192.168.99.101   minikube   <none>           <none>
MacBook-Pro:exercise chunyinjiang$ kubectl get nodes -o wide
NAME       STATUS   ROLES    AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE               KERNEL-VERSION   CONTAINER-RUNTIME
minikube   Ready    master   2d5h   v1.18.3   192.168.99.101   <none>        Buildroot 2019.02.10   4.19.107         docker://19.3.8

这边讲一下vm虚拟机,安装了vmbox,可以直接打开客户端,你会发现一个minikube的虚拟机在运行,你可以直接在这边登陆root,不需要密码,也可以用其他的终端ssh登陆上面的master主机来查看相关信息:ssh docker@192.168.99.101 现在我们ssh到我们的master节点,默认用户名:docker 密码:tcuser

也可以直接使用minikube ssh来直接连接登陆。

k8s进程

$ ps -ef | grep kube
root      3977  3936  1 Jun10 ?        00:22:19 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=/var/lib/minikube/certs/ca.crt --cluster-name=mk --cluster-signing-cert-file=/var/lib/minikube/certs/ca.crt --cluster-signing-key-file=/var/lib/minikube/certs/ca.key --controllers=*,bootstrapsigner,tokencleaner --kubeconfig=/etc/kubernetes/controller-manager.conf --leader-elect=true --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --root-ca-file=/var/lib/minikube/certs/ca.crt --service-account-private-key-file=/var/lib/minikube/certs/sa.key --use-service-account-credentials=true
root      4012  3947  0 Jun10 ?        00:04:57 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
root      4046  3967  1 Jun10 ?        00:24:05 etcd --advertise-client-urls=https://192.168.99.101:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --initial-advertise-peer-urls=https://192.168.99.101:2380 --initial-cluster=minikube=https://192.168.99.101:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.99.101:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.99.101:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt
root      4066  3993  3 Jun10 ?        00:55:50 kube-apiserver --advertise-address=192.168.99.101 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/var/lib/minikube/certs/ca.crt --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --enable-bootstrap-token-auth=true --etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt --etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=8443 --service-account-key-file=/var/lib/minikube/certs/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/minikube/certs/apiserver.crt --tls-private-key-file=/var/lib/minikube/certs/apiserver.key
docker    4155  4114  0 06:49 pts/0    00:00:00 grep kube
root      4362     1  2 Jun10 ?        00:38:48 /var/lib/minikube/binaries/v1.18.3/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=systemd --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=docker --fail-swap-on=false --hostname-override=minikube --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.99.101 --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 --pod-manifest-path=/etc/kubernetes/manifests
root      4688  4668  0 Jun10 ?        00:00:35 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=minikube

k8s镜像

$ docker images
REPOSITORY                                                                    TAG                 IMAGE ID            CREATED             SIZE
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy                v1.18.3             3439b7546f29        3 weeks ago         117MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler            v1.18.3             76216c34ed0c        3 weeks ago         95.3MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager   v1.18.3             da26705ccb4b        3 weeks ago         162MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver            v1.18.3             7e28efa976bd        3 weeks ago         173MB
registry.cn-hangzhou.aliyuncs.com/google_containers/dashboard                 v2.0.0              8b32422733b3        7 weeks ago         222MB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause                     3.2                 80d28bedfe5d        3 months ago        683kB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns                   1.6.7               67da37a9a360        4 months ago        43.8MB
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd                      3.4.3-0             303ce5db0e90        7 months ago        288MB
registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-scraper           v1.0.2              3b08661dc379        7 months ago        40.1MB
registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner       v1.8.1              4689081edb10        2 years ago         80.8MB

管理集群

查看状态

MacBook-Pro:exercise chunyinjiang$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

开启dashboard

minikube dashborad启动pod
kubernetes-dashboard   dashboard-metrics-scraper-84bfdf55ff-m6hlx   1/1     Running   0          4d20h
kubernetes-dashboard   kubernetes-dashboard-696dbcc666-vfrks        1/1     Running   0          4d20h

然后可以

MacBook-Pro:~ chunyinjiang$ minikube dashboard --url
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
http://127.0.0.1:59625/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

其实还有有用的组件都是通过插件模式可以开启的

列出当前支持的插件

MacBook-Pro:exercise chunyinjiang$ minikube addons list
|-----------------------------|----------|--------------|
|         ADDON NAME          | PROFILE  |    STATUS    |
|-----------------------------|----------|--------------|
| ambassador                  | minikube | disabled     |
| dashboard                   | minikube | enabled ✅   |
| default-storageclass        | minikube | enabled ✅   |
| efk                         | minikube | disabled     |
| freshpod                    | minikube | disabled     |
| gvisor                      | minikube | disabled     |
| helm-tiller                 | minikube | disabled     |
| ingress                     | minikube | disabled     |
| ingress-dns                 | minikube | disabled     |
| istio                       | minikube | disabled     |
| istio-provisioner           | minikube | disabled     |
| logviewer                   | minikube | disabled     |
| metallb                     | minikube | disabled     |
| metrics-server              | minikube | disabled     |
| nvidia-driver-installer     | minikube | disabled     |
| nvidia-gpu-device-plugin    | minikube | disabled     |
| olm                         | minikube | disabled     |
| registry                    | minikube | disabled     |
| registry-aliases            | minikube | disabled     |
| registry-creds              | minikube | disabled     |
| storage-provisioner         | minikube | enabled ✅   |
| storage-provisioner-gluster | minikube | disabled     |
|-----------------------------|----------|--------------|

开启插件

例如 metrics-server:

minikube addons enable metrics-server

关闭插件

minikube addons disable metrics-server

登陆minikube虚拟机

miniube ssh

停止集群

minikube stop

删除集群

minikube delete
minikube delete --all

查看minikube的状态

$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

查看minikube的服务列表

$ minikube service list
|----------------------|-----------------------------------|--------------|-----------------------------|
|      NAMESPACE       |               NAME                | TARGET PORT  |             URL             |
|----------------------|-----------------------------------|--------------|-----------------------------|
| default              | kubernetes                        | No node port |
| default              | nginx                             | http/80      | http://192.168.99.101:30080 |
| default              | redis-master                      | No node port |
| default              | redis-slave                       | No node port |
| kruise-system        | kruise-controller-manager-service | No node port |
| kruise-system        | kruise-webhook-server-service     | No node port |
| kube-system          | elasticsearch-logging             | No node port |
| kube-system          | etcd-k8s                          | No node port |
| kube-system          | kibana-logging                    |         5601 | http://192.168.99.101:30003 |
| kube-system          | kube-dns                          | No node port |
| kube-system          | kube-scheduler                    | No node port |
| kube-system          | kubelet                           | No node port |
| kube-system          | metrics-server                    | No node port |
| kubernetes-dashboard | dashboard-metrics-scraper         | No node port |
| kubernetes-dashboard | kubernetes-dashboard              | No node port |
| monitoring           | alertmanager-main                 | web/9093     | http://192.168.99.101:31234 |
| monitoring           | alertmanager-operated             | No node port |
| monitoring           | grafana                           | http/3000    | http://192.168.99.101:30267 |
| monitoring           | kube-state-metrics                | No node port |
| monitoring           | node-exporter                     | No node port |
| monitoring           | prometheus-adapter                | No node port |
| monitoring           | prometheus-k8s                    | web/9090     | http://192.168.99.101:31174 |
| monitoring           | prometheus-operated               | No node port |
| monitoring           | prometheus-operator               | No node port |
|----------------------|-----------------------------------|--------------|-----------------------------|

Pause Kubernetes without impacting deployed applications:

minikube pause

Halt the cluster:

minikube stop

Increase the default memory limit (requires a restart):

minikube config set memory 16384

Browse the catalog of easily installed Kubernetes services:

minikube addons list

Create a second cluster running an older Kubernetes release:

minikube start -p aged --kubernetes-version=v1.16.1

Delete all of the minikube clusters:

minikube delete --all

大体上minikube到这边也就够用了,如果还需要深入研究,可以去看minikubekubernetes官方文档。

集群

真正生产使用的k8s都是集群部署的,所以在部署这一块也是比较重要的,社区和各个大厂都有着不同的部署运维方案,我们需要重点研究一下[k8s的集群部署]()。

在 1.4版本之前都是手动部署,在1.4之后提供了部署工具kubeadm,kubeadm帮忙大大优化了k8s的部署,所以目前有两种部署方式,当然kubeadm是对手动部署的封装,目前大部分还是使用手动部署k8s,熟悉启动参数意义,当然大家都在做部署工具,后面使用kubeadm是一种趋势。

首先不管什么部署,一些机器上的基础工作都是一样需要做

1、关闭防火墙

systemctl stop firewalld

设置开启不启动

systemctl disable firewalld

关闭SELINUX

setenforce 0

永久关闭

SELINUX sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

2、安装iptables

yum install iptables -y
yum install iptables-services -y

清空iptables规则

iptables -F
iptables -X
iptables -Z
iptables -F -t nat
service iptables save

3、ntpdate 时间同步

ntpdate time1.aliyun.com

kubeadm

其实在一开始企业级的k8s的部署一直是一个问题,基本上都是使用传统的kvm部署方式,比如ansible,supervisord,slat,可能这些项目本身的学习就要比k8s还要高,使得k8s一直是一个高门槛的技术。 后来在2017年才有社区推动,发布了这个kubeadm项目(值得一一提的是这个项目是一个18岁的高中生写的,这就是开源项目的魅力)

kubeadm是Kubernetes 1.4开始新增的特性,用于快速搭建Kubernetes集群环境,两个命令就能把一个k8s集群搭建起来。

原理

kubeadm把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。

为什么不能使用容器运行kubelet?

kubelet除了跟容器运行时打交道外,kubelet 在配置容器网络、管理容器数据卷时,都需要直接操作宿主机。而如果现在 kubelet 本身就运行在一个容器里,那么直接操作宿主机就会变得很麻烦。对于网络配置来说还好,kubelet 容器可以通过不开启 Network Namespace(即 Docker 的 host network 模式)的方式,直接共享宿主机的网络栈。可是,要让 kubelet 隔着容器的 Mount Namespace 和文件系统,操作宿主机的文件系统,就有点儿困难了。

命令

kubeadm一共提供了5个子命令:

kubeadm init
kubeadm join
kubeadm token
kubeadm reset
kubeadm version

正常我们使用两个命令就可以搭建k8s集群了。

# 创建一个Master节点
$ kubeadm init
# 将一个Node节点加入到当前集群中
$ kubeadm join

kubeadm init的主要工作

  • 创建集群安全相关的的key、certs和conf文件。
  • 创建kube-apiserver、kube-controller-manager、kube-scheduler、etcd(如果没有配置external etcd)这些static pod的json格式的manifest文件,kubelet负责启动这些master组件。
  • 通过addons方式启动kube-discovery deployment、kube-proxy daemonSet、kube-dns deployment。

kubeadm join主要负责创建kubelet.conf,使kubelet能与API Server建立连接:

  • 访问kube-discovery服务获取cluster info(包含cluster ca证书、API Server endpoint列表和token。
  • 利用定的token,检验cluster info的签名。
  • 检验成功后,再与API Server建立连接,请求API Server为该node创建证书。
  • 根据获取到的证书创建kubelet.conf。

随着Kubernetes 1.13 的发布,现在Kubeadm正式成为GA。之前都是测试版本,并不能用于生产。

手动部署

shell一键部署

上面kubeadm是一种部署方式的趋势,在现在很多情况下还不够成熟,都在探索,在这个过度期间大部分都会使用shell脚本进行一键部署。

这一块就比较偏运维,需要写大量的运维脚本,使用一些成熟的运维工具,比如puppet,cobbler,absible,supervisor等,都是服务器自动化部署及运维常见工具

二进制部署

就是我们最常用的手动部署方式,也是需要多次练习了解的。

权限设置

1、设置ca证书和秘钥

安装ssl

  wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
  wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
  wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64

  sudo cp cfssl_linux-amd64 /usr/local/bin/cfssl 
  sudo cp cfssljson_linux-amd64 /usr/local/bin/cfssljson
  sudo cp cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

  cd /usr/local/bin/ 

  chmod +x cfssl
  chmod +x cfssljson
  chmod +x cfssl-certinfo

初始化

mkdir ~/cfssl
cd ~/cfssl
cfssl print-defaults config > ca-config.json
cfssl print-defaults csr > ca-csr.json

创建ca中心

cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF

ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;

signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;

server auth:表示client可以用该 CA 对server提供的证书进行验证;

client auth:表示server可以用该CA对client提供的证书进行验证;

创建 CA 证书签名请求文件

创建 ca-csr.json 文件,内容如下:

{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

“CN”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;

“O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca

生产对应的ca证书,如下:

[root@promesdevapp18 ssl]# vi ca-config.json
[root@promesdevapp18 ssl]# vi ca-csr.json
[root@promesdevapp18 ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2019/04/11 11:06:53 [INFO] generating a new CA key and certificate from CSR
2019/04/11 11:06:53 [INFO] generate received request
2019/04/11 11:06:53 [INFO] received CSR
2019/04/11 11:06:53 [INFO] generating key: rsa-2048
2019/04/11 11:06:54 [INFO] encoded CSR
2019/04/11 11:06:54 [INFO] signed certificate with serial number 551260756352944283434991089528819033235135295505
[root@promesdevapp18 ssl]# ll
total 18828
-rw-r--r-- 1 root root      292 Apr 11 11:06 ca-config.json
-rw-r--r-- 1 root root     1001 Apr 11 11:06 ca.csr
-rw-r--r-- 1 root root      208 Apr 11 11:06 ca-csr.json
-rw------- 1 root root     1679 Apr 11 11:06 ca-key.pem
-rw-r--r-- 1 root root     1359 Apr 11 11:06 ca.pem
-rwxrwxrwx 1 root root  6595195 Apr 11 11:02 cfssl-certinfo_linux-amd64
-rwxrwxrwx 1 root root  2277873 Apr 11 11:02 cfssljson_linux-amd64
-rwxrwxrwx 1 root root 10376657 Apr 11 11:02 cfssl_linux-amd64

生成运行CA所必需的文件ca-key.pem(私钥)和ca.pem(证书),还会生成ca.csr(证书签名请求),用于交叉签名或重新签名。

请保持ca-key.pem文件的安全。此密钥允许在CA中创建任何类型的证书。*.csr 文件在整个过程中不会使用

这边所有ca相关证书就是根证书,用于签发下面的每个组件的证书,在这个集群中,他就是权威机构,最高权限,默认签发的证书是一年,需要注意修改。

2、创建 kubernetes 证书

创建 kubernetes 证书签名请求文件 kubernetes-csr.json:

{
    "CN": "kubernetes",
    "hosts": [
      "127.0.0.1",
      "192.168.56.107",
      "192.168.56.106",
      "192.168.56.105",
      "10.254.0.1",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "BeiJing",
            "L": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}

如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 etcd 集群和 kubernetes master 集群使用,所以上面分别指定了 etcd 集群、kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.254.0.1)。

这是最小化安装的kubernetes集群,包括一个私有镜像仓库,三个节点的kubernetes集群,以上物理节点的IP也可以更换为主机名。

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes -hostname="127.0.0.1,192.168.56.107,192.168.56.106,192.168.56.105,10.254.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local" kubernetes-csr.json | cfssljson -bare kubernetes

或者

echo '{"CN":"kubernetes","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes -hostname="127.0.0.1,172.20.0.112,172.20.0.113,172.20.0.114,172.20.0.115,kubernetes,kubernetes.default" - | cfssljson -bare kubernetes

生成kubernetes的对应三个文件

[root@promesdevapp18 ssl]# vi kubernetes-csr.json
[root@promesdevapp18 ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes -hostname="127.0.0.1,10.47.210.31,10.47.210.30,10.47.210.94,10.254.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local" kubernetes-csr.json | cfssljson -bare kubernetes
2019/04/11 11:45:17 [INFO] generate received request
2019/04/11 11:45:17 [INFO] received CSR
2019/04/11 11:45:17 [INFO] generating key: rsa-2048
2019/04/11 11:45:17 [INFO] encoded CSR
2019/04/11 11:45:17 [INFO] signed certificate with serial number 4144021668890124555398076217136881830789156682
[root@promesdevapp18 ssl]#
[root@promesdevapp18 ssl]#
[root@promesdevapp18 ssl]# ll
total 18844
-rw-r--r-- 1 root root      292 Apr 11 11:43 ca-config.json
-rw-r--r-- 1 root root     1001 Apr 11 11:44 ca.csr
-rw-r--r-- 1 root root      209 Apr 11 11:44 ca-csr.json
-rw------- 1 root root     1679 Apr 11 11:44 ca-key.pem
-rw-r--r-- 1 root root     1359 Apr 11 11:44 ca.pem
-rwxrwxrwx 1 root root  6595195 Apr 11 11:02 cfssl-certinfo_linux-amd64
-rwxrwxrwx 1 root root  2277873 Apr 11 11:02 cfssljson_linux-amd64
-rwxrwxrwx 1 root root 10376657 Apr 11 11:02 cfssl_linux-amd64
-rw-r--r-- 1 root root     1261 Apr 11 11:45 kubernetes.csr
-rw-r--r-- 1 root root      556 Apr 11 11:45 kubernetes-csr.json
-rw------- 1 root root     1675 Apr 11 11:45 kubernetes-key.pem
-rw-r--r-- 1 root root     1627 Apr 11 11:45 kubernetes.pem

3、创建 admin 证书

创建 admin 证书签名请求文件 admin-csr.json:

{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}

后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;

kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的所有 API的权限;

O 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;

注意:这个admin 证书,是将来生成管理员用的kube config 配置文件用的,现在我们一般建议使用RBAC 来对kubernetes 进行角色权限控制, kubernetes 将证书中的CN 字段 作为User, O 字段作为 Group(具体参考 Kubernetes中的用户与身份认证授权中 X509 Client Certs 一段)。

在搭建完 kubernetes 集群后,我们可以通过命令: kubectl get clusterrolebinding cluster-admin -o yaml ,查看到 clusterrolebinding cluster-admin 的 subjects 的 kind 是 Group,name 是 system:masters。 roleRef 对象是 ClusterRole cluster-admin。 意思是凡是 system:masters Group 的 user 或者 serviceAccount 都拥有 cluster-admin 的角色。 因此我们在使用 kubectl 命令时候,才拥有整个集群的管理权限。可以使用 kubectl get clusterrolebinding cluster-admin -o yaml 来查看。

生成 admin 证书和私钥:

$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin

4、创建 kube-proxy 证书

创建 kube-proxy 证书签名请求文件 kube-proxy-csr.json:

{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

CN 指定该证书的 User 为 system:kube-proxy;

kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

生成 kube-proxy 客户端证书和私钥

$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy
$ ls kube-proxy*

5、校验证书

1.openssl

$ openssl x509  -noout -text -in  kubernetes.pem



确认 Issuer 字段的内容和 ca-csr.json 一致;
确认 Subject 字段的内容和 kubernetes-csr.json 一致;
确认 X509v3 Subject Alternative Name 字段的内容和 kubernetes-csr.json 一致;
确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.json 中 kubernetes profile 一致;

2.cfssl-certinfo

使用 cfssl-certinfo 命令

$ cfssl-certinfo -cert kubernetes.pem

6、分发证书

将生成的证书和秘钥文件(后缀名为.pem)拷贝到所有机器的 /etc/kubernetes/ssl 目录下备用

7、创建kubectl kubeconfig

先在master上安装kubectl

创建 kubectl kubeconfig 文件

export MASTER_IP=192.168.56.107
export KUBE_APISERVER="https://${MASTER_IP}:6443"

设置集群参数

kubectl config set-cluster kubernetes \
  --certificate-authority=/home/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER}

设置客户端认证参数

kubectl config set-credentials admin \
  --client-certificate=/home/ssl/admin.pem \
  --embed-certs=true \
  --client-key=/home/ssl/admin-key.pem

设置上下文参数

kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=admin

设置默认上下文

kubectl config use-context kubernetes

admin.pem 证书 OU 字段值为 system:masters,kube-apiserver 预定义的 RoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 相关 API 的权限;

生成的 kubeconfig 被保存到 ~/.kube/config 文件;

注意:~/.kube/config文件拥有对该集群的最高权限,请妥善保管。

8、TLS Bootstrapping使用kubeapiserver给kubelet生成证书

kubelet、kube-proxy 等 Node 机器上的进程与 Master 机器的 kube-apiserver 进程通信时需要认证和授权;

kubernetes 1.4 开始支持由 kube-apiserver 为客户端生成 TLS 证书的 TLS Bootstrapping 功能,这样就不需要为每个客户端生成证书了;该功能当前仅支持为 kubelet 生成证书;

以下操作只需要在master节点上执行,生成的*.kubeconfig文件可以直接拷贝到node节点的/etc/kubernetes目录下。

创建 TLS Bootstrapping Token

export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF

BOOTSTRAP_TOKEN 将被写入到 kube-apiserver 使用的 token.csv 文件和 kubelet 使用的 bootstrap.kubeconfig 文件,如果后续重新生成了 BOOTSTRAP_TOKEN,则需要:

1.更新 token.csv 文件,分发到所有机器 (master 和 node)的 /etc/kubernetes/ 目录下,分发到node节点上非必需; 2.重新生成 bootstrap.kubeconfig 文件,分发到所有 node 机器的 /etc/kubernetes/ 目录下; 3.重启 kube-apiserver 和 kubelet 进程; 4.重新 approve kubelet 的 csr 请求; 5.cp token.csv /etc/kubernetes/

9、创建 kubelet bootstrapping kubeconfig 文件

cd /etc/kubernetes

export MASTER_IP=192.168.56.107
export KUBE_APISERVER="https://${MASTER_IP}:6443"

设置集群参数

kubectl config set-cluster kubernetes \
  --certificate-authority=/home/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=bootstrap.kubeconfig

设置客户端认证参数

kubectl config set-credentials kubelet-bootstrap \
  --token=${BOOTSTRAP_TOKEN} \
  --kubeconfig=bootstrap.kubeconfig

设置上下文参数

kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=bootstrap.kubeconfig

设置默认上下文

kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

–embed-certs 为 true 时表示将 certificate-authority 证书写入到生成的 bootstrap.kubeconfig 文件中;

设置客户端认证参数时没有指定秘钥和证书,后续由 kube-apiserver 自动生成;

10、创建 kube-proxy kubeconfig 文件

cd /etc/kubernetes
export KUBE_APISERVER="https://192.168.56.107:6443"

设置集群参数

kubectl config set-cluster kubernetes \
  --certificate-authority=/home/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig

设置客户端认证参数

kubectl config set-credentials kube-proxy \
  --client-certificate=/home/ssl/kube-proxy.pem \
  --client-key=/home/ssl/kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

设置上下文参数

kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig

设置默认上下文

kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

设置集群参数和客户端认证参数时 –embed-certs 都为 true,这会将 certificate-authority、client-certificate 和 client-key 指向的证书文件内容写入到生成的 kube-proxy.kubeconfig 文件中;

kube-proxy.pem 证书中 CN 为 system:kube-proxy,kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

分发:

将两个 kubeconfig 文件分发到所有 Node 机器的 /etc/kubernetes/ 目录

cp bootstrap.kubeconfig kube-proxy.kubeconfig /etc/kubernetes/

安装etcd—–带tls的

本次安装用到的变量设置

$ export NODE_NAME=opt6 # 当前部署的机器名称(随便定义,只要能区分不同机器即可)
$ export NODE_IP=192.168.56.107 # 当前部署的机器 IP
$ export NODE_IPS="192.168.56.107 192.168.56.106 192.168.56.105" # etcd 集群所有机器 IP
$ # etcd 集群间通信的IP和端口
$ export ETCD_NODES=opt6=https://192.168.56.105:2380,opt7=https://192.168.56.106:2380,opt8=https://192.168.56.107:2380
$ # 导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR
$ source /root/local/bin/environment.sh

1.设置etcd二进制文件

Etcd是Kubernetes集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息。

整个kubernetes系统中一共有两个服务需要用到etcd用来协同和存储配置,分别是:

网络插件flannel、对于其它网络插件也需要用到etcd存储网络的配置信息
kubernetes本身,包括各种对象的状态和元信息配置

目前使用etcd版本3.1.6

wget https://github.com/coreos/etcd/releases/download/v3.1.5/etcd-v3.1.5-linux-amd64.tar.gz

解压设置环境变量

tar -xvf etcd-v3.1.5-linux-amd64.tar.gz
echo 'export PATH=/home/etcd/etcd-v3.1.6-linux-amd64:$PATH' >> /etc/profile
source /etc/profile

或者把二进制文件移到系统路径下,比如/usr/local/src

2.创建 etcd的TLS 秘钥和证书

编辑etcd-csr.json

cat > etcd-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "192.168.56.107"----设置本地ip,也就是上面的${NODE_IP}
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

生成 etcd 证书和私钥:

cfssl gencert -ca=/home/ssl/ca.pem \
  -ca-key=/home/ssl/ca-key.pem \
  -config=/home/ssl/ca-config.json \
  -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

这边可以使用kubernete的证书,因为证书包含了etcd节点

因为包含主机的ip每台机器的证书都要单独生成,不能拷贝

3.创建 etcd 的 systemd unit 文件

在/usr/lib/systemd/system/目录下创建文件etcd.service

opt8

cat > etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/home/etcd/etcd-v3.1.6-linux-amd64/etcd \\
  --name=opt8 \\
  --cert-file=/home/ssl/etcd.pem \\
  --key-file=/home/ssl/etcd-key.pem \\
  --peer-cert-file=/home/ssl/etcd.pem \\
  --peer-key-file=/home/ssl/etcd-key.pem \\
  --trusted-ca-file=/home/ssl/ca.pem \\
  --peer-trusted-ca-file=/home/ssl/ca.pem \\
  --initial-advertise-peer-urls=https://192.168.56.107:2380 \\
  --listen-peer-urls=https://192.168.56.107:2380 \\
  --listen-client-urls=https://192.168.56.107:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://192.168.56.107:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=opt8=https://192.168.56.107:2380,opt7=https://192.168.56.106:2380,opt6=https://192.168.56.105:2380 \\
  --initial-cluster-state=new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

opt7

cat > etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/home/etcd/etcd-v3.1.6-linux-amd64/etcd \\
  --name=opt7 \\
  --cert-file=/home/ssl/etcd.pem \\
  --key-file=/home/ssl/etcd-key.pem \\
  --peer-cert-file=/home/ssl/etcd.pem \\
  --peer-key-file=/home/ssl/etcd-key.pem \\
  --trusted-ca-file=/home/ssl/ca.pem \\
  --peer-trusted-ca-file=/home/ssl/ca.pem \\
  --initial-advertise-peer-urls=https://192.168.56.106:2380 \\
  --listen-peer-urls=https://192.168.56.106:2380 \\
  --listen-client-urls=https://192.168.56.106:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://192.168.56.106:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=opt8=https://192.168.56.107:2380,opt7=https://192.168.56.106:2380,opt6=https://192.168.56.105:2380 \\
  --initial-cluster-state=new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

opt6

cat > etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/home/etcd/etcd-v3.1.6-linux-amd64/etcd \\
  --name=opt6 \\
  --cert-file=/home/ssl/etcd.pem \\
  --key-file=/home/ssl/etcd-key.pem \\
  --peer-cert-file=/home/ssl/etcd.pem \\
  --peer-key-file=/home/ssl/etcd-key.pem \\
  --trusted-ca-file=/home/ssl/ca.pem \\
  --peer-trusted-ca-file=/home/ssl/ca.pem \\
  --initial-advertise-peer-urls=https://192.168.56.105:2380 \\
  --listen-peer-urls=https://192.168.56.105:2380 \\
  --listen-client-urls=https://192.168.56.105:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://192.168.56.105:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=opt8=https://192.168.56.107:2380,opt7=https://192.168.56.106:2380,opt6=https://192.168.56.105:2380 \\
  --initial-cluster-state=new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

启动参数在service中不用加“”,否则启动失败。

也可以使用命令行启动

opt8

etcd -name niub1 -debug \
    -initial-advertise-peer-urls http://192.168.56.107:2380 \
    -listen-peer-urls http://192.168.56.107:2380 \
    -listen-client-urls http://192.168.56.107:2379,http://127.0.0.1:2379 \
    -advertise-client-urls http://192.168.56.107:2379 \
    -initial-cluster-token etcd-cluster-1 \
    -initial-cluster niub1=http://192.168.56.107:2380,niub2=http://192.168.56.106:2380,niub3=http://192.168.56.105:2380 \
    -initial-cluster-state new  >> ./etcd.log 2>&1 &

opt7

etcd -name niub2 -debug \
    -initial-advertise-peer-urls http://192.168.56.106:2380 \
    -listen-peer-urls http://192.168.56.106:2380 \
    -listen-client-urls http://192.168.56.106:2379,http://127.0.0.1:2379 \
    -advertise-client-urls http://192.168.56.106:2379 \
    -initial-cluster-token etcd-cluster-1 \
    -initial-cluster niub1=http://192.168.56.107:2380,niub2=http://192.168.56.106:2380,niub3=http://192.168.56.105:2380 \
    -initial-cluster-state new  >> ./etcd.log 2>&1 &

opt6

etcd -name niub3 -debug \
    -initial-advertise-peer-urls http://192.168.56.105:2380 \
    -listen-peer-urls http://192.168.56.105:2380 \
    -listen-client-urls http://192.168.56.105:2379,http://127.0.0.1:2379 \
    -advertise-client-urls http://192.168.56.105:2379 \
    -initial-cluster-token etcd-cluster-1 \
    -initial-cluster niub1=http://192.168.56.107:2380,niub2=http://192.168.56.106:2380,niub3=http://192.168.56.105:2380 \
    -initial-cluster-state new  >> ./etcd.log 2>&1 &

4.加载service,启动

systemctl daemon-reload
systemctl enable etcd
systemctl start etcd

5.测试集群—这个是带ca的

etcdctl \
  --ca-file=/home/ssl/ca.pem \
  --cert-file=/home/ssl/kubernetes.pem \
  --key-file=/home/ssl/kubernetes-key.pem \
  cluster-health

查看集群中k8s的数据

Kubenretes1.6中使用etcd V3版本的API,使用etcdctl直接ls的话只能看到/kube-centos一个路径。需要在命令前加上ETCDCTL_API=3这个环境变量才能看到kuberentes在etcd中保存的数据。

ETCDCTL_API=3 etcdctl get /registry/namespaces/default -w=json|python -m json.tool

-w指定输出格式

使用–prefix可以看到所有的子目录,如查看集群中的namespace:

ETCDCTL_API=3 etcdctl get /registry/namespaces --prefix -w=json|python -m json.tool

key的值是经过base64编码,需要解码后才能看到实际值,如:

[root@opt8 ssl]# echo L3JlZ2lzdHJ5L25hbWVzcGFjZXMva3ViZS1zeXN0ZW0=|base64 -d
/registry/namespaces/kube-system[root@opt8 ssl]#

etcd中kubernetes的元数据

#!/bin/bash
# Get kubernetes keys from etcd
export ETCDCTL_API=3
keys=`etcdctl get /registry --prefix -w json|python -m json.tool|grep key|cut -d ":" -f2|tr -d '"'|tr -d ","`
for x in $keys;do
  echo $x|base64 -d|sort
done

我们可以看到所有的Kuberentes的所有元数据都保存在/registry目录下,下一层就是API对象类型(复数形式),再下一层是namespace,最后一层是对象的名字。

master安装

部署机器

10.47.210.30

部署组件

kube-apiserver
kube-controller-manager
kube-scheduler

1、配置和启动 kube-apiserver

创建 kube-apiserver 使用的客户端 token 文件

kubelet 首次启动时向 kube-apiserver 发送 TLS Bootstrapping 请求,kube-apiserver 验证 kubelet 请求中的 token 是否与它配置的 token.csv 一致,如果一致则自动为 kubelet生成证书和秘钥。

目录

/etc/systemd/system


cat  > kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
ExecStart=/usr/bin/kube-apiserver \
  --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
  --advertise-address=10.47.210.30 \
  --insecure-bind-address=10.47.210.30 \
  --authorization-mode=RBAC \
  --runtime-config=rbac.authorization.k8s.io/v1alpha1 \
  --kubelet-https=true \
  --enable-bootstrap-token-auth \
  --service-cluster-ip-range=10.254.0.0/16 \
  --service-node-port-range=8400-9000 \
  --etcd-cafile=/root/ssl/ca.pem \
  --etcd-certfile=/root/ssl/etcd.pem \
  --etcd-keyfile=/root/ssl/etcd-key.pem \
  --etcd-servers=https://10.47.210.30:2379,https://10.47.210.31:2379,https://10.47.210.94:2379 \
  --enable-swagger-ui=true \
  --allow-privileged=true \
  --apiserver-count=3 \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/var/lib/audit.log \
  --event-ttl=1h \
  --v=0 \
  --logtostderr=true \
  --bind-address=10.47.210.30 \
  --token-auth-file=/etc/kubernetes/token.csv \
  --tls-cert-file=/root/ssl/kubernetes.pem \
  --tls-private-key-file=/root/ssl/kubernetes-key.pem \
  --client-ca-file=/root/ssl/ca.pem \
  --service-account-key-file=/root/ssl/ca-key.pem
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

参数解析

  • –v=2 日志级别,debug级别是0
  • –logtostderr=false 不输出到logerr
  • –allow-privileged=true 使用docker run –privileged
  • –etcd-servers=“” etcd的集群地,kube-apiserver 1.6 版本开始使用 etcd v3 API 和存储格式
  • –insecure-bind-address 非安全端口监听的ip
  • –advertise-address=192.168.14.132 自身地址
  • –bind-address=0.0.0.0 安全端口监听的ip
  • –log-dir=/data/log/kubernetes/kube-apiserver 日志路径,我们一般根据这些参数来查看日志路径,然后去查看相关日志
  • –authorization-mode=RBAC 指定在安全端口使用 RBAC 授权模式,拒绝未通过授权的请求
  • –admission-control 值必须包含 ServiceAccount,否则部署集群插件时会失败
  • –bind-address 绑定地址,不能为 127.0.0.1
  • –service-cluster-ip-range=10.252.0.0/16 指定 Service Cluster IP 地址段,该地址段不能路由可达,如果中途修改过–service-cluster-ip-range地址,则必须将default命名空间的kubernetes的service给删除,使用命令:kubectl delete service kubernetes,然后系统会自动用新的ip重建这个service,不然apiserver的log有报错the cluster IP x.x.x.x for service kubernetes/default is not within the service CIDR x.x.x.x/16; please recreate
  • –service-node-port-range=30000-40000 指定 NodePort 的端口范围,
  • –experimental-bootstrap-token-auth Bootstrap Token Authentication在1.9版本已经变成了正式feature,参数名称改为–enable-bootstrap-token-auth
  • –insecure-port=8080 开通http的无认证的接口
  • –insecure-bind-address=127.0.0.1。注意,生产上不要绑定到非127.0.0.1的地址上

启动

systemctl daemon-reload
systemctl enable kube-apiserver
systemctl start kube-apiserver
systemctl status kube-apiserver

2、创建 kube-controller-manager 的 systemd unit 文件

cat > kube-controller-manager.service <<EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/bin/kube-controller-manager \
  --address=127.0.0.1 \
  --master=http://10.47.210.30:8080 \
  --allocate-node-cidrs=true \
  --service-cluster-ip-range=10.254.0.0/16 \
  --cluster-cidr=172.30.0.0/16 \
  --cluster-name=kubernetes \
  --leader-elect=true \
  --v=2 \
  --cluster-signing-cert-file=/root/ssl/ca.pem \
  --cluster-signing-key-file=/root/ssl/ca-key.pem  \
  --service-account-private-key-file=/root/ssl/ca-key.pem \
  --root-ca-file=/root/ssl/ca.pem
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

参数解析

–address值必须是127.0.0.1,因为当前的kube-apiserver期望scheduler和controller-manager在同一台机器上

–master=http://{MASTER_IP}:8080:使用非安全 8080 端口与 kube-apiserver 通信;

–cluster-cidr 指定 Cluster 中 Pod 的 CIDR 范围,该网段在各 Node 间必须路由可达(flanneld保证);

–service-cluster-ip-range 参数指定 Cluster 中 Service 的CIDR范围,该网络在各 Node 间必须路由不可达,必须和 kube-apiserver 中的参数一致;

–cluster-signing-* 指定的证书和私钥文件用来签名为 TLS BootStrap 创建的证书和私钥;

–root-ca-file 用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件;

–leader-elect=true 部署多台机器组成的 master 集群时选举产生一处于工作状态的 kube-controller-manager 进程;

启动 kube-controller-manager

systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl start kube-controller-manager
systemctl status kube-controller-manager

我们启动每个组件后可以通过执行命令kubectl get componentstatuses,来查看各个组件的状态;

$ kubectl get componentstatuses
NAME                 STATUS      MESSAGE                                                                                        ERROR
scheduler            Unhealthy   Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: getsockopt: connection refused
controller-manager   Healthy     ok
etcd-2               Healthy     {"health": "true"}
etcd-0               Healthy     {"health": "true"}
etcd-1               Healthy     {"health": "true"}

3、创建 kube-scheduler 的 systemd unit 文件

cat > kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/bin/kube-scheduler \
  --address=127.0.0.1 \
  --master=http://10.47.210.30:8080 \
  --leader-elect=true \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

参数解析

–address 值必须为 127.0.0.1,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;

–master=http://{MASTER_IP}:8080:使用非安全 8080 端口与 kube-apiserver 通信;

–leader-elect=true 部署多台机器组成的 master 集群时选举产生一处于工作状态的 kube-controller-manager 进程;

启动

systemctl daemon-reload
systemctl enable kube-scheduler
systemctl start kube-scheduler
systemctl status kube-scheduler

验证 master 节点功能

$ kubectl get componentstatuses
NAME                 STATUS    MESSAGE              ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
etcd-0               Healthy   {"health": "true"}
etcd-1               Healthy   {"health": "true"}
etcd-2               Healthy   {"health": "true"}

node部署

部署机器

10.47.210.30
10.47.210.31
10.47.210.94

部署组件

flannel
docker
kubelet
kube-proxy

1、flannel

1.安装二进制文件

Flannel是作为一个二进制文件的方式部署在每个node上,主要实现两个功能:

1.为每个node分配subnet,容器将自动从该子网中获取IP地址

2.当有node加入到网络中时,为每个node增加路由配置

目前使用版本默认安装的是0.7.1版本的flannel。

wget  https://github.com/coreos/flannel/releases/download/v0.7.1/flannel-v0.7.1-linux-amd64.tar.gz

我没有下载下来,直接github下载

解压设置环境变量

tar -zxvf flannel-v0.7.1-linux-amd64.tar.gz
echo 'export PATH=/home/flannel:$PATH' >> /etc/profile
source /etc/profile

或者把二进制文件移到系统路径下,比如/usr/local/src

2.创建ca证书

cat > flanneld-csr.json <<EOF
{
  "CN": "flanneld",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

生成 flanneld 证书和私钥:

$ cfssl gencert -ca=/home/ssl/ca.pem \
  -ca-key=/home/ssl/ca-key.pem \
  -config=/home/ssl/ca-config.json \
  -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld

拷贝到所有主机

向 etcd 写入集群 Pod 网段信息

etcdctl \
  --endpoints=https://10.47.210.30:2379,https://10.47.210.31:2379,https://10.47.210.94:2379 \
  --ca-file=/root/ssl/ca.pem \
  --cert-file=/root/ssl/flanneld.pem \
  --key-file=/root/ssl/flanneld-key.pem \
  set /kubernetes/network/config '{"Network":"'172.30.0.0/16'", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}'

写入的 Pod 网段(${CLUSTER_CIDR},172.30.0.0/16) 必须与 kube-controller-manager 的 –cluster-cidr 选项值一致;

也可以这样写

etcdctl --endpoints=https://192.168.56.107:2379,https://192.168.56.106:2379,https://192.168.56.105:2379 \
  --ca-file=/home/ssl/ca.pem \
  --cert-file=/home/ssl/kubernetes.pem \
  --key-file=/home/ssl/kubernetes-key.pem \
  mkdir /kubernetes/network
etcdctl --endpoints=https://192.168.56.107:2379,https://192.168.56.106:2379,https://192.168.56.105:2379 \
  --ca-file=/home/ssl/ca.pem \
  --cert-file=/home/ssl/kubernetes.pem \
  --key-file=/home/ssl/kubernetes-key.pem \
  mk /kubernetes/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'

如果你要使用host-gw模式,可以直接将vxlan改成host-gw即可

创建 flanneld 的 systemd unit 文件

目录

/usr/lib/systemd/system



cat > flanneld.service << EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/usr/bin/flanneld \\
  -etcd-cafile=/root/ssl/ca.pem \\
  -etcd-certfile=/root/ssl/flanneld.pem \\
  -etcd-keyfile=/root/ssl/flanneld-key.pem \\
  -etcd-endpoints=https://10.47.210.30:2379,https://10.47.210.31:2379,https://10.47.210.94:2379 \
  -etcd-prefix=/kubernetes/network \\
  -iface=eth0
ExecStartPost=/root/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
EOF

在参数最后有空格也会导致启动失败

etcd集群启动了双向tls认证,所以需要为flanneld指定与etcd集群通信的ca和密钥

mk-docker-opts.sh脚本将分配给flanneld的pod子网网段信息写入到/run/flannel/docker文件中,后续docker启动时使用这个文件中参数值设置为docker0的网桥

-iface 选项指定flanneld和其他node通信的接口,如果机器有内外网,则最好指定为内网接口

4.加载service,启动

systemctl daemon-reload
systemctl enable flanneld
systemctl start flanneld
systemctl status flanneld

检查 flanneld 服务

$ journalctl  -u flanneld |grep 'Lease acquired'
$ ifconfig flannel.1

查看集群 Pod 网段(/16)

$ /root/local/bin/etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/flanneld/ssl/flanneld.pem \
  --key-file=/etc/flanneld/ssl/flanneld-key.pem \
  get ${FLANNEL_ETCD_PREFIX}/config
{ "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "vxlan" } }

查看已分配的 Pod 子网段列表(/24)

$ /root/local/bin/etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/flanneld/ssl/flanneld.pem \
  --key-file=/etc/flanneld/ssl/flanneld-key.pem \
  ls ${FLANNEL_ETCD_PREFIX}/subnets
/kubernetes/network/subnets/172.30.19.0-24

查看某一 Pod 网段对应的 flanneld 进程监听的 IP 和网络参数

$ /root/local/bin/etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/flanneld/ssl/flanneld.pem \
  --key-file=/etc/flanneld/ssl/flanneld-key.pem \
  get ${FLANNEL_ETCD_PREFIX}/subnets/172.30.19.0-24
{"PublicIP":"10.64.3.7","BackendType":"vxlan","BackendData":{"VtepMAC":"d6:51:2e:80:5c:69"}}

确保各节点间 Pod 网段能互联互通

在各节点上部署完 Flannel 后,查看已分配的 Pod 子网段列表(/24)

etcdctl \
  --endpoints=https://192.168.56.107:2379,https://192.168.56.106:2379,https://192.168.56.105:2379 \
  --ca-file=/home/ssl/ca.pem \
  --cert-file=/home/ssl/kubernetes.pem \
  --key-file=/home/ssl/kubernetes-key.pem \
  ls /kubernetes/network/subnets
/kubernetes/network/subnets/172.30.19.0-24
/kubernetes/network/subnets/172.30.20.0-24
/kubernetes/network/subnets/172.30.21.0-24

当前三个节点分配的 Pod 网段分别是:172.30.19.0-24、172.30.20.0-24、172.30.21.0-24。

在各节点上分配 ping 这三个网段的网关地址,确保能通:

$ ping 172.30.19.1
$ ping 172.30.20.2
$ ping 172.30.21.3

3、docker

安装和配置 docker

下载最新的 docker 二进制文件

$ wget https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz
$ tar -xvf docker-17.04.0-ce.tgz
$ cp docker/docker* /root/local/bin
$ cp docker/completion/bash/docker /etc/bash_completion.d/

创建 docker 的 systemd unit 文件

cat > docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.io

[Service]
Environment="PATH=/root/local/bin:/bin:/sbin:/usr/bin:/usr/sbin"
EnvironmentFile=-/run/flannel/docker
ExecStart=/usr/bin/dockerd --log-level=error $DOCKER_NETWORK_OPTIONS
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

dockerd 运行时会调用其它 docker 命令,如 docker-proxy,所以需要将 docker 命令所在的目录加到 PATH 环境变量中;

flanneld 启动时将网络配置写入到 /run/flannel/docker 文件中的变量 DOCKER_NETWORK_OPTIONS,dockerd 命令行上指定该变量值来设置 docker0 网桥参数;

如果指定了多个 EnvironmentFile 选项,则必须将 /run/flannel/docker 放在最后(确保 docker0 使用 flanneld 生成的 bip 参数);

不能关闭默认开启的 –iptables 和 –ip-masq 选项;

如果内核版本比较新,建议使用 overlay 存储驱动;

docker 从 1.13 版本开始,可能将 iptables FORWARD chain的默认策略设置为DROP,从而导致 ping 其它 Node 上的 Pod IP 失败,遇到这种情况时,需要手动设置策略为 ACCEPT:

$ sudo iptables -P FORWARD ACCEPT
$

并且把以下命令写入/etc/rc.local文件中,防止节点重启iptables FORWARD chain的默认策略又还原为DROP

sleep 60 && /sbin/iptables -P FORWARD ACCEPT

为了加快 pull image 的速度,可以使用国内的仓库镜像服务器,同时增加下载的并发数。(如果 dockerd 已经运行,则需要重启 dockerd 生效。)

  $ cat /etc/docker/daemon.json
  {
    "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn", "hub-mirror.c.163.com"],
    "max-concurrent-downloads": 10
  }

启动

systemctl daemon-reload
systemctl stop firewalld
systemctl disable firewalld
iptables -F && sudo iptables -X && sudo iptables -F -t nat && sudo iptables -X -t nat
systemctl enable docker
systemctl start docker

如果指定了多个 EnvironmentFile 选项,则必须将 /run/flannel/docker 放在最后(确保 docker0 使用 flanneld 生成的 bip 参数);

4、kubelet

kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper 角色,然后 kubelet 才有权限创建认证请求(certificatesigningrequests):

$ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
$

–user=kubelet-bootstrap 是文件 /etc/kubernetes/token.csv 中指定的用户名,同时也写入了文件 /etc/kubernetes/bootstrap.kubeconfig;

下载最新的 kubelet 和 kube-proxy 二进制文件

$ wget https://dl.k8s.io/v1.6.2/kubernetes-server-linux-amd64.tar.gz
$ tar -xzvf kubernetes-server-linux-amd64.tar.gz
$ cd kubernetes
$ tar -xzvf  kubernetes-src.tar.gz
$ sudo cp -r ./server/bin/{kube-proxy,kubelet} /root/local/bin/

创建 kubelet 的 systemd unit 文件

$ sudo mkdir /var/lib/kubelet # 必须先创建工作目录


cat > kubelet.service <<EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/bin/kubelet \\
  --address=10.47.210.30 \\
  --hostname-override=10.47.210.30 \\
  --pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest \\
  --bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \\
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
  --cert-dir=/root/ssl \\
  --cluster-dns=10.254.0.2 \\
  --cluster-domain=cluster.local. \\
  --hairpin-mode promiscuous-bridge \\
  --allow-privileged=true \\
  --serialize-image-pulls=false \\
  --logtostderr=true \\
  --runtime-cgroups=/systemd/system.slice \\
  --kubelet-cgroups=/systemd/system.slice \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP

参数解析

–address 不能设置为 127.0.0.1,否则后续 Pods 访问 kubelet 的 API 接口时会失败,因为 Pods 访问的 127.0.0.1 指向自己而不是 kubelet;

如果设置了 –hostname-override 选项,则 kube-proxy 也需要设置该选项,否则会出现找不到 Node 的情况;

–experimental-bootstrap-kubeconfig 指向 bootstrap kubeconfig 文件,kubelet 使用该文件中的用户名和 token 向 kube-apiserver 发送 TLS Bootstrapping 请求;

管理员通过了 CSR 请求后,kubelet 自动在 –cert-dir 目录创建证书和私钥文件(kubelet-client.crt 和 kubelet-client.key),然后写入 –kubeconfig 文件;

建议在 –kubeconfig 配置文件中指定 kube-apiserver 地址,如果未指定 –api-servers 选项,则必须指定 –require-kubeconfig 选项后才从配置文件中读取 kube-apiserver 的地址,否则 kubelet 启动后将找不到 kube-apiserver (日志中提示未找到 API Server),kubectl get nodes 不会返回对应的 Node 信息;1.14不再支持require-kubeconfig选项

–cluster-dns 指定 kubedns 的 Service IP(可以先分配,后续创建 kubedns 服务时指定该 IP),–cluster-domain 指定域名后缀,这两个参数同时指定后才会生效;

对于kuberentes1.8集群中的kubelet配置,取消了KUBELET_API_SERVER的配置,而改用kubeconfig文件来定义master地址,所以请注释掉–api-servers=http://172.20.0.113:8080配置。

如果使用systemd方式启动,则需要额外增加两个参数–runtime-cgroups=/systemd/system.slice –kubelet-cgroups=/systemd/system.slice,1.14不加也可以

–experimental-bootstrap-kubeconfig 在1.9版本已经变成了–bootstrap-kubeconfig

”–cgroup-driver 配置成 systemd,不要使用cgroup,否则在 CentOS 系统中 kubelet 将启动失败(保持docker和kubelet中的cgroup driver配置一致即可,不一定非使用systemd)。

–cluster-domain 指定 pod 启动时 /etc/resolve.conf 文件中的 search domain ,起初我们将其配置成了 cluster.local.,这样在解析 service 的 DNS 名称时是正常的,可是在解析 headless service 中的 FQDN pod name 的时候却错误,因此我们将其修改为 cluster.local,去掉嘴后面的 ”点号“ 就可以解决该问题,关于 kubernetes 中的域名/服务名称解析请参见我的另一篇文章。

–kubeconfig=/etc/kubernetes/kubelet.kubeconfig中指定的kubelet.kubeconfig文件在第一次启动kubelet之前并不存在,请看下文,当通过CSR请求后会自动生成kubelet.kubeconfig文件,如果你的节点上已经生成了~/.kube/config文件,你可以将该文件拷贝到该路径下,并重命名为kubelet.kubeconfig,所有node节点可以共用同一个kubelet.kubeconfig文件,这样新添加的节点就不需要再创建CSR请求就能自动添加到kubernetes集群中。同样,在任意能够访问到kubernetes集群的主机上使用kubectl –kubeconfig命令操作集群时,只要使用~/.kube/config文件就可以通过权限认证,因为这里面已经有认证信息并认为你是admin用户,对集群拥有所有权限。

KUBELET_POD_INFRA_CONTAINER 是基础镜像容器,这里我用的是私有镜像仓库地址,大家部署的时候需要修改为自己的镜像。我上传了一个到时速云上,可以直接 docker pull index.tenxcloud.com/jimmy/pod-infrastructure 下载。pod-infrastructure镜像是Redhat制作的,大小接近80M,下载比较耗时,其实该镜像并不运行什么具体进程,可以使用Google的pause镜像gcr.io/google_containers/pause-amd64:3.0,这个镜像只有300多K,或者通过DockerHub下载jimmysong/pause-amd64:3.0。

kubelet cAdvisor 默认在所有接口监听 4194 端口的请求,对于有外网的机器来说不安全,ExecStartPost 选项指定的 iptables 规则只允许内网机器访问 4194 端口;

不支持

启动错误

1.遇到kubelet报错,该服务每没隔几秒重启一下,然后自动停止。日志提示信息中有一行:container_manager_linux.go:205] Running with swap on is not supported, please disable swap! This will be a fatal error by default starting in K8s v1.6!。尝试关闭swap再试,虽然日志中没有该提示信息了,

一、不重启电脑,禁用启用swap,立刻生效

1、禁用命令

sudo swapoff -a

2、启用命令

sudo swapon -a

3、查看交换分区的状态

sudo free -m

二、重新启动电脑,永久禁用Swap

1、把根目录文件系统设为可读写

sudo mount -n -o remount,rw /

2、用vi修改/etc/fstab文件,在swap分区这行前加 # 禁用掉,保存退出

vi /etc/fstab

i      #进入insert 插入模式

:wq   #保存退出

3、重新启动电脑,使用free -m查看分区状态

reboot

sudo free -m

相对于kubernetes1.6集群必须进行的配置有:

对于kuberentes1.8集群,必须关闭swap,否则kubelet启动将失败。

修改/etc/fstab将,swap系统注释掉。

2.failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: “cgroupfs”

修改docker的cgroup驱动

vim /lib/systemd/system/docker.service
# 将 --exec-opt native.cgroupdriver=systemd  修改为:
#  --exec-opt native.cgroupdriver=cgroupfs
# systemctl daemon-reload 
# systemctl restart docker.service
# kubelet显示正常

3.重启了docker后还要重启kubelet,这时又遇到问题,kubelet启动失败。报错:

Mar 31 16:44:41 sz-pg-oam-docker-test-002.tendcloud.com kubelet[81047]: error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"
这是kubelet与docker的cgroup driver不一致导致的,kubelet启动的时候有个—cgroup-driver参数可以指定为"cgroupfs"或者“systemd”。

--cgroup-driver string                                    Driver that the kubelet uses to manipulate cgroups on the host.  Possible values: 'cgroupfs', 'systemd' (default "cgroupfs")
配置docker的service配置文件/usr/lib/systemd/system/docker.service,设置ExecStart中的--exec-opt native.cgroupdriver=systemd。

启动

systemctl daemon-reload
systemctl enable kubelet
systemctl start kubelet
systemctl status kubelet

通过 kubelet 的 TLS 证书请求

kubelet 首次启动时向 kube-apiserver 发送证书签名请求,必须通过后 kubernetes 系统才会将该 Node 加入到集群。

查看未授权的 CSR 请求:

$ kubectl get csr
NAME        AGE       REQUESTOR           CONDITION
csr-2b308   4m        kubelet-bootstrap   Pending
$ kubectl get nodes
No resources found.

通过 CSR 请求:

$ kubectl certificate approve csr-2b308
certificatesigningrequest "csr-2b308" approved



$ kubectl get nodes
NAME        STATUS    AGE       VERSION
10.64.3.7   Ready     49m       v1.6.2

自动生成了 kubelet kubeconfig 文件和公私钥:

$ ls -l /etc/kubernetes/kubelet.kubeconfig
-rw------- 1 root root 2284 Apr  7 02:07 /etc/kubernetes/kubelet.kubeconfig
$ ls -l /etc/kubernetes/ssl/kubelet*
-rw-r--r-- 1 root root 1046 Apr  7 02:07 /etc/kubernetes/ssl/kubelet-client.crt
-rw------- 1 root root  227 Apr  7 02:04 /etc/kubernetes/ssl/kubelet-client.key
-rw-r--r-- 1 root root 1103 Apr  7 02:07 /etc/kubernetes/ssl/kubelet.crt
-rw------- 1 root root 1675 Apr  7 02:07 /etc/kubernetes/ssl/kubelet.key

2、kube-proxy

创建 kube-proxy 的 systemd unit 文件

$ sudo mkdir -p /var/lib/kube-proxy # 必须先创建工作目录




cat > kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/usr/bin/kube-proxy \
  --bind-address=10.47.210.30 \
  --hostname-override=10.47.210.30 \
  --cluster-cidr=172.30.0.0/16 \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \
  --logtostderr=true \
  --v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

参数解析

–hostname-override 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 iptables 规则;

–cluster-cidr 必须与 kube-controller-manager 的 –cluster-cidr 选项值一致;

kube-proxy 根据 –cluster-cidr 判断集群内部和外部流量,指定 –cluster-cidr 或 –masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT;

–kubeconfig 指定的配置文件嵌入了 kube-apiserver 的地址、用户名、证书、秘钥等请求和认证信息;

预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

启动

systemctl daemon-reload
systemctl enable kube-proxy
systemctl start kube-proxy
systemctl status kube-proxy

到这边集群就已经手动部署完成了,可以直接使用了。

harbor

私有镜像仓库是我们自己使用k8s集群必须要使用的,可以使用原生的registry,目前最活跃的就是harbor,是国人写的,各种比较友好,最好使用1.7.5版本之后的

harbor是直接使用docker-compose单机编排的

所以安装docker和docker-compose

#下载离线安装软件
wget http://harbor.orientsoft.cn/harbor-v1.3.0-rc4/harbor-offline-installer-v1.3.0-rc4.tgz
#解压文件
tar -zxf harbor-offline-installer-v1.3.0-rc4.tgz
#解压后的文件夹是harbor

修改配置文件:域名,端口,密码,存放路径

然后直接使用harbor目录中的install.sh就可以安装启动了,然后就可以根据域名+port来访问,当然我们正常使用的情况下都是会在harbor前加一层nginx转发,这个nginx需要注意转发大小的设置

基本使用

kubectl

我们可以通过三种方式来访问apiserver提供的接口

  1. REST API

    其实就是apiserver自身提供的api,比如访问nodes,我们可以访问/api/v1/proxy/nodes/{names}。

  2. 各种语言的client lib

    我们最常用的就是client-go

  3. 命令行kubectl

    我们最直接的就是使用kubectl来看各种应用的情况

安装

我是macOS 系统并使用 Homebrew 包管理器,通过 Homebrew 安装 kubectl。

运行安装命令:

brew install kubernetes-cli

测试以确保您安装的版本是最新的:

MacBook-Pro:minikube chunyinjiang$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-21T14:51:23Z", GoVersion:"go1.14.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:43:34Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

当然也可以下载二进制文件进行安装

通过以下命令下载 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,请将上述命令中的 $(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) 部分替换成为需要下载的 kubectl 的具体版本即可。

例如,如果需要下载 v1.18.0 版本在 macOS 系统上,需要使用如下命令:

    curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/darwin/amd64/kubectl
    修改所下载的 kubectl 二进制文件为可执行模式。

    chmod +x ./kubectl
    将 kubectl 可执行文件放置到你的 PATH 目录下。

    sudo mv ./kubectl /usr/local/bin/kubectl

配置

kubectl默认情况下,kubectl 会从 $HOME/.kube 目录下查找文件名为 config 的文件。我们在上面使用minikube start的时候,自动生成了对应的默认config,可以通过设置环境变量 KUBECONFIG (环境变量 KUBECONFIG 保存一个 kubeconfig 文件列表。对于 Linux 和 Mac 系统,列表使用冒号将文件名进行分隔;对于 Windows 系统,则以分号分隔。)或者通过设置 –kubeconfig 去指定其它 kubeconfig 文件。

我们看一下这个默认的配置

MacBook-Pro:exercise chunyinjiang$ cat ~/.kube/config
apiVersion: v1
clusters:(集群,下面是集群相关的信息)
- cluster:
    certificate-authority: /Users/chunyinjiang/.minikube/ca.crt
    server: https://192.168.99.101:8443
  name: minikube
contexts:(上下文,关联集群,用户和命名空间)
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:(用户,下面是用户相关的信息)
- name: minikube
  user:
    client-certificate: /Users/chunyinjiang/.minikube/profiles/minikube/client.crt
    client-key: /Users/chunyinjiang/.minikube/profiles/minikube/client.key

我们可以看到配置文件中有三部分:

  • cluster(集群): 存储api-server的CA根证书、api-server地址、集群名称等。
  • user(用户): 真正配置用户认证时的凭证信息,使用不同的认证策略,包含不同的字段。
  • context(上下文): 把cluster和user关联起来组成一个集群环境信息,声明通过哪个user连哪个cluster。

kubeconfig 文件可以包含 context 元素,每个 context 都是一个由(集群、命名空间、用户)描述的三元组。您可以使用 kubectl config use-context 去设置当前的 context。命令行工具 kubectl 与当前 context 中指定的集群和命名空间进行通信,并且使用当前 context 中包含的用户凭证。

命令配置

手动编辑config文件非常麻烦,kubectl config子命令提供了大部分的参数自动填充kubeconfig文件,分别对应set-cluster、set-credentials、set-context,相对应的有get-clusters、get-contexts以及delete-cluster、delete-context,目前没有对应credential get和delete操作,只能手动编辑kubeconfig文件。

kubeconfig生成有三步

1、设置集群信息

kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}

集群参数主要设置了所需要访问的集群的信息。

  • set-cluster设置了需要访问的集群,如上为kubernetes;
  • –certificate-authority设置了该集群的公钥;
  • –embed-certs为true表示将–certificate-authority证书写入到kubeconfig中;
  • –server则表示该集群的kube-apiserver地址。

2、设置用户信息

kubectl config set-credentials admin   --client-certificate=/etc/kubernetes/ssl/admin.pem   --embed-certs=true   --client-key=/etc/kubernetes/ssl/admin-key.pem

用户参数主要设置用户的相关信息,主要是用户证书。

  • 用户名为admin,
  • 证书为:/etc/kubernetes/ssl/admin.pem,
  • 私钥为:/etc/kubernetes/ssl/admin-key.pem。注意客户端的证书首先要经过集群CA的签署,否则不会被集群认可。此处使用的是ca认证方式,也可以使用token认证,如kubelet的 TLS Boostrap机制下的bootstrapping使用的就是token认证方式。

3、设置上下文

kubectl config set-context kubernetes   --cluster=kubernetes   --user=admin #可以指定路径kubeconfig=/root/config.conf

上下文参数将集群参数和用户参数关联起来。

  • 上下文名称为kubenetes,集群为kubenetes,用户为admin,表示使用admin的用户凭证来访问kubenetes集群的default命名空间,也可以增加–namspace来指定访问的命名空间。

4、设置当前使用的上下文

kubectl config use-context kubernetes

配置对多集群的访问

1、通过context来完成配置

假设用户有两个集群,一个用于正式开发工作(development),一个用于其它临时用途(scratch)。 在 development 集群中,有两个开发者,前端开发者在名为 frontend 的命名空间下工作, 存储开发者在名为 storage 的命名空间下工作。 在 scratch 集群中, 开发人员可能在默认命名空间下工作,也可能视情况创建附加的命名空间。

访问开发集群需要通过证书进行认证。 访问其它临时用途的集群需要通过用户名和密码进行认证。

创建名为 config-demo 的文件,其内容为:

apiVersion: v1
kind: Config
preferences: {}

clusters:
- cluster:
  name: development
- cluster:
  name: scratch

users:
- name: developer
- name: experimenter

contexts:
- context:
  name: dev-frontend
- context:
  name: dev-storage
- context:
  name: exp-scratch

配置文件描述了集群、用户名和上下文。 config-demo 文件中含有描述两个集群、两个用户和三个上下文的框架,根据上面的描述然后进行配置

  • 将群集详细信息添加到配置文件中:

    kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file
    kubectl config --kubeconfig=config-demo set-cluster scratch --server=https://5.6.7.8 --insecure-skip-tls-verify
    
  • 将用户详细信息添加到配置文件中:

    kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile
    kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password
    
  • 将上下文详细信息添加到配置文件中:

    kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer
    kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer
    kubectl config --kubeconfig=config-demo set-context exp-scratch --cluster=scratch --namespace=default --user=experimenter
    

打开 config-demo 文件查看添加的详细信息。 也可以使用 config view 命令进行查看:

kubectl config --kubeconfig=config-demo view

输出展示了两个集群、两个用户和三个上下文:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: fake-ca-file
    server: https://1.2.3.4
  name: development
- cluster:
    insecure-skip-tls-verify: true
    server: https://5.6.7.8
  name: scratch
contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
- context:
    cluster: development
    namespace: storage
    user: developer
  name: dev-storage
- context:
    cluster: scratch
    namespace: default
    user: experimenter
  name: exp-scratch
current-context: ""
kind: Config
preferences: {}
users:
- name: developer
  user:
    client-certificate: fake-cert-file
    client-key: fake-key-file
- name: experimenter
  user:
    password: some-password
    username: exp

每个上下文包含三部分(集群、用户和命名空间),例如, dev-frontend 上下文表明:使用 developer 用户的凭证来访问 development 集群的 frontend 命名空间。

设置当前上下文:

kubectl config --kubeconfig=config-demo use-context dev-frontend

现在当输入 kubectl 命令时,相应动作会应用于 dev-frontend 上下文中所列的集群和命名空间,同时,命令会使用 dev-frontend 上下文中所列用户的凭证。

使用 –minify 参数,来查看与当前上下文相关联的配置信息。

kubectl config --kubeconfig=config-demo view --minify

输出结果展示了 dev-frontend 上下文相关的配置信息:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: fake-ca-file
    server: https://1.2.3.4
  name: development
contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
current-context: dev-frontend
kind: Config
preferences: {}
users:
- name: developer
  user:
    client-certificate: fake-cert-file
    client-key: fake-key-file

现在假设用户希望在其它临时用途集群中工作一段时间。

将当前上下文更改为 exp-scratch:

kubectl config --kubeconfig=config-demo use-context exp-scratch

现在用户 kubectl 下达的任何命令都将应用于 scratch 集群的默认命名空间。 同时,命令会使用 exp-scratch 上下文中所列用户的凭证。

查看更新后的当前上下文 exp-scratch 相关的配置:

kubectl config --kubeconfig=config-demo view --minify

最后,假设用户希望在 development 集群中的 storage 命名空间下工作一段时间。

将当前上下文更改为 dev-storage:

kubectl config --kubeconfig=config-demo use-context dev-storage

查看更新后的当前上下文 dev-storage 相关的配置:

kubectl config --kubeconfig=config-demo view --minify

2、通过多个配置文件

创建名为 config-demo-2 的文件,其中包含以下内容:

apiVersion: v1
kind: Config
preferences: {}

contexts:
- context:
    cluster: development
    namespace: ramp
    user: developer
  name: dev-ramp-up

上述配置文件定义了一个新的上下文,名为 dev-ramp-up。

临时添加两条路径到 KUBECONFIG 环境变量中。 例如,在 Linux 中:

export  KUBECONFIG=$KUBECONFIG:config-demo:config-demo-2

在 config-exercise 目录中输入以下命令:

kubectl config view

输出展示了 KUBECONFIG 环境变量中所列举的所有文件合并后的信息。 特别地, 注意合并信息中包含来自 config-demo-2 文件的 dev-ramp-up 上下文和来自 config-demo 文件的三个上下文:

contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
- context:
    cluster: development
    namespace: ramp
    user: developer
  name: dev-ramp-up
- context:
    cluster: development
    namespace: storage
    user: developer
  name: dev-storage
- context:
    cluster: scratch
    namespace: default
    user: experimenter
  name: exp-scratch

更多关于 kubeconfig 文件如何合并的信息可以去查看官方文档。

检查配置

通过获取集群状态检查 kubectl 是否被正确配置:

kubectl cluster-info

如果您看到一个 URL 被返回,那么 kubectl 已经被正确配置,能够正常访问您的 Kubernetes 集群。

如果您看到类似以下的信息被返回,那么 kubectl 没有被正确配置,无法正常访问您的 Kubernetes 集群。

The connection to the server <server-name:port> was refused - did you specify the right host or port?

如果 kubectl cluster-info 能够返回 url 响应,但您无法访问您的集群,可以使用下面的命令检查配置是否正确:

kubectl cluster-info dump

启用 shell 自动补全功能

kubectl 支持自动补全功能,可以节省大量输入!

自动补全脚本由 kubectl 产生,您仅需要在您的 shell 配置文件中调用即可。

以下仅提供了使用命令补全的常用示例,更多详细信息,请查阅 kubectl completion -h 帮助命令的输出。

1、Linux 系统,使用 bash

在 CentOS Linux系统上,您可能需要安装默认情况下未安装的 bash-completion 软件包。

yum install bash-completion -y

执行 source <(kubectl completion bash) 命令在您目前正在运行的 shell 中开启 kubectl 自动补全功能。

可以将上述命令添加到 shell 配置文件中,这样在今后运行的 shell 中将自动开启 kubectl 自动补全:

echo "source <(kubectl completion bash)" >> ~/.bashrc

2、macOS 系统,使用 bash

macOS 系统需要先通过 Homebrew 安装 bash-completion:

如果您运行的是 macOS 自带的 Bash 3.2,请运行:

brew install bash-completion

如果您使用的是 Bash 4.1+,请运行:

brew install bash-completion@2

请根据 Homebrew 输出的”注意事项(caveats)”部分的内容将 bash-completion 的路径添加到本地 .bashrc 文件中。

如果您是按照 Homebrew 指示中的步骤安装的 kubectl,那么无需其他配置,kubectl 的自动补全功能已经被启用。

如果您是手工下载并安装的 kubectl,那么您需要将 kubectl 自动补全添加到 bash-completion:

kubectl completion bash > $(brew --prefix)/etc/bash_completion.d/kubectl

由于 Homebrew 项目与 Kubernetes 无关,所以并不能保证 bash-completion 总能够支持 kubectl 的自动补全功能。

3、macOS 系统,使用 Zsh

如果您使用的是 zsh,请编辑 ~/.zshrc 文件并添加以下代码以启用 kubectl 自动补全功能。

if [ $commands[kubectl] ]; then
  source <(kubectl completion zsh)
fi

如果您使用的是 Oh-My-Zsh,请编辑 ~/.zshrc 文件并更新 plugins= 行以包含 kubectl 插件。

plugins=(kubectl)

使用

kubectl的原理是将输入的转化为REST API来调用,将返回结果输出。只是对REST API的一种封装,可以说是apiserver的一个客户端。

用法:

kubectl [command] [options]

比较核心和常用的命令都在上面的图中,这边对主要命令做一个简单的说明。

1、kubectl annotate

更新某个资源的注解,支持的资源包括但不限于(大小写不限):pods (po)、services (svc)、 replicationcontrollers (rc)、nodes (no)、events (ev)、componentstatuses (cs)、 limitranges (limits)、persistentvolumes (pv)、persistentvolumeclaims (pvc)、 resourcequotas (quota)和secrets。

示例

# 更新pod “foo”,设置其注解description的值为my frontend。
# 如果同一个注解被赋值了多次,只保存最后一次设置的值。
$ kubectl annotate pods foo description='my frontend'

# 更新“pod.json”文件中type和name字段指定的pod的注解。
$ kubectl annotate -f pod.json description='my frontend'

# 更新pod “foo”,设置其注解description的值为my frontend running nginx,已有的值将被覆盖。
$ kubectl annotate --overwrite pods foo description='my frontend running nginx'

# 更新同一namespace下所有的pod。
$ kubectl annotate pods --all description='my frontend running nginx'

# 仅当pod “foo”当前版本为1时,更新其注解
$ kubectl annotate pods foo description='my frontend running nginx' --resource-version=1

# 更新pod “foo”,删除其注解description。
# 不需要--override选项。
$ kubectl annotate pods foo description-

2、kubectl api-versions

以“组/版本”的格式输出服务端支持的API版本。

3、kubectl apply

通过文件名或控制台输入,对资源进行配置。

示例

# 将pod.json中的配置应用到pod,当然yaml也可以
$ kubectl apply -f ./pod.json

# 将控制台输入的JSON配置应用到Pod
$ cat pod.json | kubectl apply -f -

4、kubectl attach

连接到一个正在运行的容器。

示例

# 获取正在运行中的pod 123456-7890的输出,默认连接到第一个容器
$ kubectl attach 123456-7890

# 获取pod 123456-7890中ruby-container的输出
$ kubectl attach 123456-7890 -c ruby-container date

# 切换到终端模式,将控制台输入发送到pod 123456-7890的ruby-container的“bash”命令,并将其输出到控制台/
# 错误控制台的信息发送回客户端。
$ kubectl attach 123456-7890 -c ruby-container -i -t

5、kubectl cluster-info

显示集群信息。

6、kubectl config

修改kubeconfig配置文件。

7、kubectl create

通过文件名或控制台输入,创建资源。

接受JSON和YAML格式的描述文件。

kubectl create -f FILENAME
kubectl create -f rc-nginx.yaml

8、kubectl delete

通过文件名、控制台输入、资源名或者label selector删除资源。

kubectl delete -f rc-nginx.yaml
kubectl delete po rc-nginx-btv4j
kubectl delete po -lapp=nginx-2

我们一般重启容器,使用kubectl是没有办法重启的,需要到对应的node节点上,然后使用docker kill,如果没有办法,就只能使用kubectl delete pod然后控制器会重启pod,当然这种情况下,pod是重启的,关于pod相关的都会发生变化,和重启容器还是有区别的。有时候删除pod,我们需要保存控制器,我们只要将副本数调整成0,也是我们常用的方法。

9、kubectl describe

输出指定的一个/多个资源的详细信息。

支持的资源包括但不限于(大小写不限):pods (po)、services (svc)、 replicationcontrollers (rc)、nodes (no)、events (ev)、componentstatuses (cs)、 limitranges (limits)、persistentvolumes (pv)、persistentvolumeclaims (pvc)、 resourcequotas (quota)和secrets。

示例

# 描述一个node
$ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal

# 描述一个pod
$ kubectl describe pods/nginx

# 描述pod.json中的资源类型和名称指定的pod
$ kubectl describe -f pod.json

# 描述所有的pod
$ kubectl describe pods

# 描述所有包含label name=myLabel的pod
$ kubectl describe po -l name=myLabel

# 描述所有被replication controller “frontend”管理的pod(rc创建的pod都以rc的名字作为前缀)
$ kubectl describe pods frontend

describe是我们常用的命令,比如我们使用describe分析node信息:

[root@xgpccsit02m010243129129 ~]# kubectl get nodes
NAME   STATUS   ROLES         AGE    VERSION
dev1   Ready    master.node   515d   v1.14.8
dev2   Ready    master.node   515d   v1.14.8
dev3   Ready    master.node   515d   v1.14.8
dev4   Ready    node          305d   v1.14.8
dev5   Ready    node          509d   v1.14.8
[root@xgpccsit02m010243129129 ~]# kubectl describe node dev5
Name:               dev5
Roles:              node
Labels:             APP=true
                    WEB=true
                    beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    dragonflyTest=true
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=dev5
                    kubernetes.io/os=linux
                    netType=B2C
                    node-network-driver=ovs
                    node-role.kubernetes.io/node=
Annotations:        csi.volume.kubernetes.io/nodeid: {"ossplugin.csi":"10.243.133.2"}
                    node.alpha.kubernetes.io/ttl: 0
                    sncloud.com/cpu-policy: none
                    sncloud.com/diskIOPSCapacity: 1000000
                    sncloud.com/gpu.usage: null
                    sncloud.com/gpu.used: 0
                    sncloud.com/networkBandwidthCapacity: 2000000000
CreationTimestamp:  Wed, 11 Dec 2019 17:20:26 +0800
Taints:             <none>
Unschedulable:      false
Conditions:
  Type                     Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                     ------  -----------------                 ------------------                ------                       -------
  ServiceReady             False   Tue, 12 May 2020 10:16:14 +0800   Tue, 12 May 2020 10:16:14 +0800   NodeServiceReadyChange       [cni status:unknown,]
  FrequentLxcfsRestart     False   Tue, 12 May 2020 10:16:30 +0800   Wed, 06 May 2020 18:26:52 +0800   NoFrequentLxcfsRestart       lxcfs is functioning properly
  FrequentKubeletRestart   False   Tue, 12 May 2020 10:16:30 +0800   Wed, 06 May 2020 18:26:52 +0800   NoFrequentKubeletRestart     kubelet is functioning properly
  FrequentDockerRestart    False   Tue, 12 May 2020 10:16:30 +0800   Wed, 06 May 2020 18:26:52 +0800   NoFrequentDockerRestart      docker is functioning properly
  OrphanedPodFileExist     False   Fri, 27 Mar 2020 01:53:49 +0800   Tue, 24 Mar 2020 12:10:13 +0800   NoOrphanedPodFileExist       OrphanedPod is not exist
  MemoryPressure           False   Tue, 12 May 2020 10:17:09 +0800   Wed, 08 Apr 2020 18:03:40 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure             False   Tue, 12 May 2020 10:17:09 +0800   Wed, 08 Apr 2020 18:03:40 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure              False   Tue, 12 May 2020 10:17:09 +0800   Wed, 08 Apr 2020 18:03:40 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready                    True    Tue, 12 May 2020 10:17:09 +0800   Thu, 07 May 2020 09:57:01 +0800   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  10.243.133.2
  Hostname:    dev5
Capacity:
 cpu:                24
 ephemeral-storage:  51877124Ki
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             263852704Ki
 pods:               110
Allocatable:
 cpu:                22
 ephemeral-storage:  47809957400
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             261653152Ki
 pods:               110
System Info:
 Machine ID:                 6328e225a9fe47d1bac0d3a6004c0ada
 System UUID:                6328e225a9fe47d1bac0d3a6004c0ada
 Boot ID:                    7b9342ff-16ae-4bcd-8631-dc367652de52
 Kernel Version:             4.18.0-80.11.1.el7.centos.sn11.x86_64
 OS Image:                   CentOS Linux 7 (Core)
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://18.9.9
 Kubelet Version:            v1.14.8
 Kube-Proxy Version:         v1.14.8
Non-terminated Pods:         (10 in total)
  Namespace                  Name                           CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                           ------------  ----------  ---------------  -------------  ---
  kube-system                cadvisor-proxy-5t9jk           100m (0%)     500m (2%)   100Mi (0%)       250Mi (0%)     18d
  kube-system                csi-ossplugin-gpvz8            0 (0%)        0 (0%)      0 (0%)           0 (0%)         4d23h
  kube-system                dfclient-cgzdm                 1 (4%)        2 (9%)      2Gi (0%)         3Gi (1%)       12d
  kube-system                filebeat-8ckl9                 3750m (17%)   4 (18%)     2273Mi (0%)      2660Mi (1%)    19d
  kube-system                machine-worker-nx2gc           100m (0%)     100m (0%)   100Mi (0%)       100Mi (0%)     126d
  kube-system                node-exporter-m8jc8            100m (0%)     200m (0%)   128Mi (0%)       256Mi (0%)     3d16h
  kube-system                node-problem-detector-qcwln    25m (0%)      200m (0%)   100Mi (0%)       100Mi (0%)     5d15h
  kube-system                preheat-worker-2sn7g           200m (0%)     500m (2%)   128Mi (0%)       512Mi (0%)     46d
  kube-system                voyage-agent-qb9rd             1100m (5%)    1100m (5%)  1124Mi (0%)      1124Mi (0%)    4d1h
  kube-system                voyage-openvswitch-ccdg8       1 (4%)        4 (18%)     1Gi (0%)         4Gi (1%)       113d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                7375m (33%)  12600m (57%)
  memory             7025Mi (2%)  12170Mi (4%)
  ephemeral-storage  0 (0%)       0 (0%)
Events:              <none>


解析

1、node的基本信息:名称,标签,创建时间
2、node当前运行的状态,node启动后会做一些自检工作,比如磁盘满了,如果满了就标注OutOfDisk=True,否则就继续检查内存是够不足,最后一切正常,就Ready=True,可以在上面查看,这种情况代表node处于健康状态,可以在上创建pod了。
3、node主机名和主机地址
4、node上的资源总量,比如cpu,内存,最大可调度pod的数量
5、node可分配的资源
6、本机系统信息:UUID,版本等
7、当前正在运行的pod的概要信息
8、已分配的资源使用情况
9、node相关的事件event

10、kubectl replace

更新替换

kubectl replace -f rc-nginx.yaml

11、kubectl patch

如果一个容器已经在运行,这时需要对一些容器属性进行修改,又不想删除容器,或不方便通过replace的方式进行更新。kubernetes还提供了一种在容器运行时,直接对容器进行修改的方式,就是patch命令.

kubectl patch pod rc-nginx-2-kpiqt -p '{"metadata":{"labels":{"app":"nginx-3"}}}'

12、kubectl edit

编辑服务端的资源。

示例

  # 编辑名为“docker-registry”的service
  $ kubectl edit svc/docker-registry

  # 使用一个不同的编辑器
  $ KUBE_EDITOR="nano" kubectl edit svc/docker-registry

  # 编辑名为“docker-registry”的service,使用JSON格式、v1 API版本
  $ kubectl edit svc/docker-registry --output-version=v1 -o json

13、kubectl exec

在容器内部执行命令。

示例

# 默认在pod 123456-7890的第一个容器中运行“date”并获取输出
$ kubectl exec 123456-7890 date

# 在pod 123456-7890的容器ruby-container中运行“date”并获取输出
$ kubectl exec 123456-7890 -c ruby-container date

# 切换到终端模式,将控制台输入发送到pod 123456-7890的ruby-container的“bash”命令,并将其输出到控制台/
# 错误控制台的信息发送回客户端。
$ kubectl exec 123456-7890 -c ruby-container -i -t -- bash -il

kubectl exec filebeat-27 -c container -n namespaces sh

14、kubectl logs

输出pod中一个容器的日志。

示例

# 返回仅包含一个容器的pod nginx的日志快照
$ kubectl logs nginx

# 返回pod ruby中已经停止的容器web-1的日志快照
$ kubectl logs -p -c ruby web-1

# 持续输出pod ruby中的容器web-1的日志
$ kubectl logs -f -c ruby web-1

# 仅输出pod nginx中最近的20条日志
$ kubectl logs --tail=20 nginx

# 持续输出pod nginx中的日志,重最近的20条日志开始
$ kubectl logs --tail=20 -f nginx

# 输出pod nginx中最近一小时内产生的所有日志
$ kubectl logs --since=1h nginx

15、kubectl version

输出服务端和客户端的版本信息。

16、kubectl get

获取信息

kubectl get po

17、kubectl rolling-update

滚动更新.

kubectl rolling-update rc-nginx-2 -f rc-nginx.yaml,

这个还提供如果在升级过程中,发现有问题还可以中途停止update,并回滚到前面版本

kubectl rolling-update rc-nginx-2 —rollback

18、kubectl scale

扩容缩容

kubectl scale rc rc-nginx-3 —replicas=4

19、kubectl cp

将文件直接拷进容器内

kubectl cp 文件 pod:路径
kubectl cp ./test.war logtestjbossforone-7b89dd5c9-297pf:/opt/wildfly/standalone/deployments

将文件重容器中拷贝到本地

kubectl cp namespace(默认是default)/pod:路径 路径
kubectl cp logtestjbossforone-7b89dd5c9-297pf:/opt/wildfly/standalone/deployments ./

20、kubectl label

给节点打上label

kubectl label nodes <node-name> <label-key>=<label-value>

可以通过–show-labels来查看node上的label

kubectl get node --show-labels

删除label

kubectl label nodes <node-name> <label-key>-

21、kubectl cordon

要标记一个节点为不可调度,执行以下命令:

kubectl cordon $NODENAME

如果标记节点为不可调度(unschedulable),将阻止新 Pod 调度到该节点之上,但不会 影响任何已经在其上的 Pod。

被 DaemonSet 控制器创建的 Pod 能够容忍节点的不可调度属性。 DaemonSet 通常提供节点本地的服务,即使节点上的负载应用已经被腾空,这些服务也仍需 运行在节点之上。

22、kubectl help

help 帮助命令,可以查找所有的命令,在我们不会用的时候,要学会使用这个命令。

kubectl其实也是k8s一个比较核心的组件,只不过体现在客户端,我们也是很有必要研究一下kubectl和核心命令的的原理

yaml文件详解

其实最后都是转化为api对象,所以符合k8s设计的顶级api对象,所以直接看顶级api对象的组成

rc实例详解

apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中
kind: ReplicationController #指定创建资源的角色/类型
metadata: #资源的元数据/属性
  name: test-rc #资源的名字,在同一个namespace中必须唯一
  labels: #设定资源的标签,详情请见http://blog.csdn.net/liyingke112/article/details/77482384
  k8s-app: apache
    software: apache
    project: test
    app: test-rc
    version: v1
  annotations:            #自定义注解列表
    - name: String        #自定义注解名字
spec:
  replicas: 2 #副本数量2
  selector: #RC通过spec.selector来筛选要控制的Pod
    software: apache
    project: test
    app: test-rc
    version: v1
    name: test-rc
  template: #这里Pod的定义
    metadata:
      labels: #Pod的label,可以看到这个label与spec.selector相同
        software: apache
        project: test
        app: test-rc
        version: v1
        name: test-rc
    spec:#specification of the resource content 指定该资源的内容
      restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器
      nodeSelector:     #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1
        zone: node1
      containers:
      - name: web04-pod #容器的名字
        image: web:apache #容器使用的镜像地址
        imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
                               # Always,每次都检查,重远程拉去
                               # Never,每次都不检查(不管本地是否有)
                               # IfNotPresent,如果本地有就不检查,如果没有就拉取
        command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
        args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
        env: #指定容器中的环境变量
        - name: str #变量的名字
          value: "/etc/run.sh" #变量的值
        resources: #资源管理,请求请见http://blog.csdn.net/liyingke112/article/details/77452630
          requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
            cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
            memory: 32Mi #内存使用量
          limits: #资源限制
            cpu: 0.5
            memory: 32Mi
        ports:
        - containerPort: 80 #容器开发对外的端口
          name: httpd  #名称
          protocol: TCP
        livenessProbe: #pod内容器健康检查的设置,详情请见http://blog.csdn.net/liyingke112/article/details/77531584
          httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
            path: / #URI地址
            port: 80
            #host: 127.0.0.1 #主机地址
            scheme: HTTP
          initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
          timeoutSeconds: 5 #检测的超时时间
          periodSeconds: 15  #检查间隔时间
          #也可以用这种方法
          #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
          #  command:
          #    - cat
          #    - /tmp/health
          #也可以用这种方法
          #tcpSocket: //通过tcpSocket检查健康
          #  port: number
        lifecycle: #生命周期管理
          postStart: #容器运行之前运行的任务
            exec:
              command:
                - 'sh'
                - 'yum upgrade -y'
          preStop:#容器关闭之前运行的任务
            exec:
              command: ['service httpd stop']
        volumeMounts:  #详情请见http://blog.csdn.net/liyingke112/article/details/76577520
        - name: volume #挂载设备的名字,与volumes[*].name 需要对应
          mountPath: /data #挂载到容器的某个路径下
          readOnly: True
  volumes: #定义一组挂载设备
  - name: volume #定义一个挂载设备的名字
    #meptyDir: {}
    hostPath:
      path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种

迁移

迁移一般用于集群的升级,k8s集群的升级比较困难,而迁移相对来说就简单很多,可以通过向新集群中逐个迁移应用,发现懂啊具体问题,而不像升级发现问题, 都难以下手或者范围比较广,比如将1.16以下的集群升级到1.16,因为api版本发生变化,在1.16中k8s删除v1 and v1beta1,所以在之前使用这些api的就需要做对应的更改,如果直接升级,就会出现很多问题。 当然升级也是可以的,需要专门的去做changelog调研,针对一些可能的问题做处理,也是可以做到无损升级的。

当然迁移也可以是迁移现有应用上云,迁移现有应用步骤说明:

  • 将原有应用拆解为服务
  • 容器化、制作镜像
  • 准备应用配置文件
  • 准备kubernetes YAML文件
  • 编写bootstarp脚本
  • 创建ConfigMaps

上云的步骤

  • 搭建基础平台,提供能力
  • 将单体应用制作镜像云上运行
  • 制定规范
  • 将中间件应用(框架,数据库,队列,负载均衡等等)上云
  • 最后在以上能力的基础上建设微服务架构,将业务上云

管理

1、陈列式

就是我们正常使用的命令行,在查,创建,删除的时候,比较好操作,但是修改就比较麻烦,使用声明式的文件方式比较好操作

2、声明式

就是我们使用的yaml或者json格式,修改文件就简单了,可以在线edit修改,也可以离线修改。

3、GUI

就是我们dashboard。

版本号管理

经常看到一串版本号v1.17.0-alpha.3.227+7d13dfe3c34f44-dirty,看起来非常复杂,其实熟悉git的同学一眼就能看出正是git的源码版本信息。

分解字段 说明
v1.17.0-alpha.3 上一次tag,表示v1.17.0的第3个alpha版本
227 上一次tag之后提交数
7d13dfe3c34f44 最新一次提交id
dirty 源码是否修改

这里描述了kubernetes的版本管理规则,据此可以看出上述版本一定是在master分支上。

问题处理

1、创建Nginx Pod过程中报如下错误:

#kubectlcreate -f nginx-pod.yaml

Error from server: error when creating "nginx-pod.yaml": Pod "nginx" is forbidden: no API token found for service account default/default, retry after the token is automatically created and added to the service account

解决方法:

修改/etc/kubernetes/apiserver文件中KUBE_ADMISSION_CONTROL参数。

修改前:

KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

去掉“ServiceAccount”选项。

2、创建Pod过程中,显示异常,通过查看日志/var/log/messages,有以下报错信息:

Nov 26 21:52:06 localhost kube-apiserver: E1126 21:52:06.697708    1963 server.go:454] Unable to generate self signed cert: open /var/run/kubernetes/apiserver.crt: permission denied
Nov 26 21:52:06 localhost kube-apiserver: E1126 21:52:06.697818    1963 server.go:464] Unable to listen for secure (open /var/run/kubernetes/apiserver.crt: no such file or directory); will try again.

解决方法有两种:

第一种方法:

# vim /usr/lib/systemd/system/kube-apiserver.service

[Service]
PermissionsStartOnly=true
ExecStartPre=-/usr/bin/mkdir /var/run/kubernetes
ExecStartPre=/usr/bin/chown -R kube:kube /var/run/kubernetes/

# systemctl daemon-reload
# systemctl restart kube-apiserver

第二种方法:

# vim /etc/kubernetes/apiserver

KUBE_API_ARGS="--secure-port=0"

在KUBE_API_ARGS加上–secure-port=0参数。

原因如下:

--secure-port=6443: The port on which to serve HTTPS with authentication and authorization. If 0, don't serve HTTPS at all.

k8s原理

k8s原理详解