.1. 前提准备 .2. 安装 Docker 和 Docker-Compose .3. 离线安装之非安全模式 .3.1. 下载安装软件 .3.2. 编辑配置文件 .3.3. 运行安装脚本 .3.4. 查看验证 .3.5. 登陆 Harbor 管理页面 .3.6. Docker 配置 .3.7. Docker 登陆 harbor .3.8. 测试上传镜像 .4. 生成自签名 .4.1. 生成证书颁发机构证书 .4.2. 生成服务器证书 .5. 离线安装之安全模式 .5.1. 下载安装软件 .5.2. 向 Harbor 提供证书 .5.3. 编辑配置文件 .5.4. 运行安装脚本 .5.5. Docker 客户端使用证书 .5.6. Docker 登陆测试 .6. 参考 .7. 关于作者 .1. 前提准备 harbor 2.4.1 版本 基于 CentOS 7 假设我们的 IP 是:192.168.100.8 自定义域名: harbor.
Minikube 安装 仅用于开产使用,生产不能使用。 以下仅以 macOS 系统演示 1.1 Docker 安装 官方下载,直接安装即可。 https://docs.docker.com/desktop/mac/install/ 使用国内镜像源,推荐阿里云的。 参考:https://yezihack.github.io/docker-install.html#docker-加速 1.2 Kubectl 安装 Kubernetes 命令行工具,kubectl,使得你可以对 Kubernetes 集群运行命令。 你可以使用 kubectl 来部署应用、监测和管理集群资源以及查看日志。 官方下载,有详细的安装流程。支持:windows, linux, macOS 参考:https://kubernetes.io/zh/docs/tasks/tools/install-kubectl-macos/ # Apple Silicon M1 cpu curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl" # Intel cpu curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" 添加权限,加入 PATH 目录 # 添加执行权限 chmod +x ./kubectl # 移动到path目录,全局可访问 sudo mv ./kubectl /usr/local/bin/kubectl sudo chown root: /usr/local/bin/kubectl # 查看版本 kubectl version --client 查看配置,了解更多 kubectl 命令
kubernetes 导航目录 第一章 kubernetes 介绍 第二章 Kubernetes 安装 第三章 Kubernetes 资源管理 第四章 Kubernetes 实战操作 第五章 Kubernetes Pod 介绍 第六章 Kubernetes Pod 控制器 第七章 Kubernetes Service 介绍 第八章 Kubernetes Ingress 介绍 第九章 Kubernetes 数据存储 第十章 Kubernetes 权限认证 第十一章 Kubernetes Dashboard 脑图 kubernetes 涉及知识点比较,难以一次全记住,将以上的关于kubernetes 讲解的知识点汇总成脑图,方便查阅,随时复习。 若下图不方便查看,直接查看原链接轻点,脑图 关于作者 我的博客:https://yezihack.github.io 欢迎关注我的微信公众号【空树之空】,共同学习,一起进步~
本章节主要介绍 kubernetes 的 Dashboard。 找不到目录, 传送门:Kubernetes 总纲及脑图 下载yaml,并运行Dashboard # 下载yaml [root@master ~]# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml # 修改kubernetes-dashboard的Service类型 kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: type: NodePort # 新增 ports: - port: 443 targetPort: 8443 nodePort: 30009 # 新增 selector: k8s-app: kubernetes-dashboard # 部署 [root@master ~]# kubectl create -f recommended.yaml # 查看namespace下的kubernetes-dashboard下的资源 [root@master ~]# kubectl get pod,svc -n kubernetes-dashboard NAME READY STATUS RESTARTS AGE pod/dashboard-metrics-scraper-c79c65bb7-zwfvw 1/1 Running 0 111s pod/kubernetes-dashboard-56484d4c5-z95z5 1/1 Running 0 111s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/dashboard-metrics-scraper ClusterIP 10.
本章节主要介绍Kubernetes的安全认证机制。 找不到目录, 传送门:Kubernetes 总纲及脑图 访问控制概述 ​ Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群中,客户端通常有两类: User Account:一般是独立于kubernetes之外的其他服务管理的用户账号。 Service Account:kubernetes管理的账号,用于为Pod中的服务进程在访问Kubernetes时提供身份标识。 认证、授权与准入控制 ApiServer是访问及管理资源对象的唯一入口。任何一个请求访问ApiServer,都要经过下面三个流程: Authentication(认证):身份鉴别,只有正确的账号才能够通过认证 Authorization(授权): 判断用户是否有权限对访问的资源执行特定的动作 Admission Control(准入控制):用于补充授权机制以实现更加精细的访问控制功能。 认证管理 Kubernetes集群安全的最关键点在于如何识别并认证客户端身份,它提供了3种客户端身份认证方式: HTTP Base认证:通过用户名+密码的方式认证 这种认证方式是把“用户名:密码”用BASE64算法进行编码后的字符串放在HTTP请求中的Header Authorization域里发送给服务端。服务端收到后进行解码,获取用户名及密码,然后进行用户身份认证的过程。 HTTP Token认证:通过一个Token来识别合法用户 这种认证方式是用一个很长的难以被模仿的字符串–Token来表明客户身份的一种方式。每个Token对应一个用户名,当客户端发起API调用请求时,需要在HTTP Header里放入Token,API Server接到Token后会跟服务器中保存的token进行比对,然后进行用户身份认证的过程。 HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式 这种认证方式是安全性最高的一种方式,但是同时也是操作起来最麻烦的一种方式。 HTTPS认证大体分为3个过程: 证书申请和下发 HTTPS通信双方的服务器向CA机构申请证书,CA机构下发根证书、服务端证书及私钥给申请者 客户端和服务端的双向认证 1> 客户端向服务器端发起请求,服务端下发自己的证书给客户端, 客户端接收到证书后,通过私钥解密证书,在证书中获得服务端的公钥, 客户端利用服务器端的公钥认证证书中的信息,如果一致,则认可这个服务器 2> 客户端发送自己的证书给服务器端,服务端接收到证书后,通过私钥解密证书, 在证书中获得客户端的公钥,并用该公钥认证证书信息,确认客户端是否合法 服务器端和客户端进行通信 服务器端和客户端协商好加密方案后,客户端会产生一个随机的秘钥并加密,然后发送到服务器端。 服务器端接收这个秘钥后,双方接下来通信的所有内容都通过该随机秘钥加密 注意: Kubernetes允许同时配置多种认证方式,只要其中任意一个方式认证通过即可 授权管理 ​ 授权发生在认证成功之后,通过认证就可以知道请求用户是谁, 然后Kubernetes会根据事先定义的授权策略来决定用户是否有权限访问,这个过程就称为授权。 ​ 每个发送到ApiServer的请求都带上了用户和资源的信息:比如发送请求的用户、请求的路径、请求的动作等,授权就是根据这些信息和授权策略进行比较,如果符合策略,则认为授权通过,否则会返回错误。 API Server目前支持以下几种授权策略: AlwaysDeny:表示拒绝所有请求,一般用于测试 AlwaysAllow:允许接收所有请求,相当于集群不需要授权流程(Kubernetes默认的策略) ABAC:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制 Webhook:通过调用外部REST服务对用户进行授权 Node:是一种专用模式,用于对kubelet发出的请求进行访问控制 RBAC:基于角色的访问控制(kubeadm安装方式下的默认选项) RBAC(Role-Based Access Control) 基于角色的访问控制,主要是在描述一件事情:给哪些对象授予了哪些权限 其中涉及到了下面几个概念: 对象:User、Groups、ServiceAccount 角色:代表着一组定义在资源上的可操作动作(权限)的集合 绑定:将定义好的角色跟用户绑定在一起 RBAC引入了4个顶级资源对象:
本章节主要介绍kubernetes的数据存储。 在前面已经提到,容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,kubernetes引入了Volume的概念。 ​ Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命容器不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。 kubernetes的Volume支持多种类型,比较常见的有下面几个: 简单存储:EmptyDir、HostPath、NFS 高级存储:PV、PVC 配置存储:ConfigMap、Secret 基本存储 EmptyDir ​ EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录。 ​ EmptyDir是在Pod被分配到Node时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为kubernetes会自动分配一个目录,当Pod销毁时, EmptyDir中的数据也会被永久删除。 EmptyDir用途如下: 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留 一个容器需要从另一个容器中获取数据的目录(多容器共享目录) 接下来,通过一个容器之间文件共享的案例来使用一下EmptyDir。 ​ 在一个Pod中准备两个容器nginx和busybox,然后声明一个Volume分别挂在到两个容器的目录中,然后nginx容器负责向Volume中写日志,busybox中通过命令将日志内容读到控制台。 创建一个volume-emptydir.yaml apiVersion: v1 kind: Pod metadata: name: volume-emptydir namespace: dev spec: containers: - name: nginx image: nginx:1.14-alpine ports: - containerPort: 80 volumeMounts: # 将logs-volume挂在到nginx容器中,对应的目录为 /var/log/nginx - name: logs-volume mountPath: /var/log/nginx - name: busybox image: busybox:1.30 command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件中内容 volumeMounts: # 将logs-volume 挂在到busybox容器中,对应的目录为 /logs - name: logs-volume mountPath: /logs volumes: # 声明volume, name为logs-volume,类型为emptyDir - name: logs-volume emptyDir: {} # 创建Pod [root@master ~]# kubectl create -f volume-emptydir.
本章节主要介绍kubernetes的流量负载组件:Ingress。 找不到目录, 传送门:Kubernetes 总纲及脑图 在前面课程中已经提到,Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点: NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显 LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持 ​ 基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示: ​ 实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务。在这里有两个核心概念: ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则 ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等 Ingress(以Nginx为例)的工作原理如下: 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置 Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新 到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则 Ingress使用 环境准备 搭建ingress环境 # 创建文件夹 [root@master ~]# mkdir ingress-controller [root@master ~]# cd ingress-controller/ # 获取ingress-nginx,本次案例使用的是0.30版本 [root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml [root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml # 修改mandatory.yaml文件中的仓库 # 修改quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0 # 为quay-mirror.qiniu.com/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0 # 创建ingress-nginx [root@master ingress-controller]# kubectl apply -f ./ # 查看ingress-nginx [root@master ingress-controller]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE pod/nginx-ingress-controller-fbf967dd5-4qpbp 1/1 Running 0 12h # 查看service [root@master ingress-controller]# kubectl get svc -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.
本章节主要介绍kubernetes的流量负载组件:Service。 Service介绍 ​ 在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。 ​ 为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。 ​ Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。 # 10.97.97.97:80 是service提供的访问入口 # 当访问这个入口的时候,可以发现后面有三个pod的服务在等待调用, # kube-proxy会基于rr(轮询)的策略,将请求分发到其中一个pod上去 # 这个规则会同时在集群内的所有节点上都生成,所以在任何一个节点上访问都可以。 [root@node1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.97.97.97:80 rr -> 10.244.1.39:80 Masq 1 0 0 -> 10.244.1.40:80 Masq 1 0 0 -> 10.244.2.33:80 Masq 1 0 0 kube-proxy目前支持三种工作模式: userspace 模式 ​ userspace模式下,kube-proxy会为每一个Service创建一个监听端口,发向Cluster IP的请求被Iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的Pod并和其建立链接,以将请求转发到Pod上。 ​ 该模式下,kube-proxy充当了一个四层负责均衡器的角色。由于kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。 iptables 模式 ​ iptables模式下,kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。 ​ 该模式下kube-proxy不承担四层负责均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。
本章节主要介绍各种Pod控制器的详细使用。 Pod控制器介绍 Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类: 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建 控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建 什么是Pod控制器 Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。 在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些: ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代 ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级 Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本 Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷 DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务 Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务 Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行 StatefulSet:管理有状态应用 ReplicaSet(RS) ReplicaSet的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容和镜像版本的升降级。 ReplicaSet的资源清单文件: apiVersion: apps/v1 # 版本号 kind: ReplicaSet # 类型 metadata: # 元数据 name: # rs名称 namespace: # 所属命名空间 labels: #标签 controller: rs spec: # 详情描述 replicas: 3 # 副本数量 selector: # 选择器,通过它指定该控制器管理哪些pod matchLabels: # Labels匹配规则 app: nginx-pod matchExpressions: # Expressions匹配规则 - {key: app, operator: In, values: [nginx-pod]} template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本 metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.
本章节将详细介绍Pod资源的各种配置(yaml)和原理。 Pod结构 每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类: 用户程序所在的容器,数量可多可少 Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个: 可以以它为依据,评估整个Pod的健康状态 可以在根容器上设置Ip地址,其它容器都此Ip(Pod IP),以实现Pod内部的网路通信 这里是Pod内部的通讯,Pod的之间的通讯采用虚拟二层网络技术来实现,我们当前环境用的是Flannel Pod定义 下面是Pod的资源清单: apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,资源类型,例如 Pod metadata: #必选,元数据 name: string #必选,Pod名称 namespace: string #Pod所属的命名空间,默认为"default" labels: #自定义标签列表 - name: string spec: #必选,Pod中容器的详细定义 containers: #必选,Pod中容器列表 - name: string #必选,容器名称 image: string #必选,容器的镜像名称 imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略 command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令 args: [string] #容器的启动命令参数列表 workingDir: string #容器的工作目录 volumeMounts: #挂载到容器内部的存储卷配置 - name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名 mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符 readOnly: boolean #是否为只读模式 ports: #需要暴露的端口库号列表 - name: string #端口的名称 containerPort: int #容器需要监听的端口号 hostPort: int #容器所在主机需要监听的端口号,默认与Container相同 protocol: string #端口协议,支持TCP和UDP,默认TCP env: #容器运行前需设置的环境变量列表 - name: string #环境变量名称 value: string #环境变量的值 resources: #资源限制和请求的设置 limits: #资源限制的设置 cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数 memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数 requests: #资源请求的设置 cpu: string #Cpu请求,容器启动的初始可用数量 memory: string #内存请求,容器启动的初始可用数量 lifecycle: #生命周期钩子 postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启 preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止 livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器 exec: #对Pod容器内检查方式设置为exec方式 command: [string] #exec方式需要制定的命令或脚本 httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port path: string port: number host: string scheme: string HttpHeaders: - name: string value: string tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式 port: number initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒 timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒 periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次 successThreshold: 0 failureThreshold: 0 securityContext: privileged: false restartPolicy: [Always | Never | OnFailure] #Pod的重启策略 nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上 nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上 imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定 - name: string hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络 volumes: #在该pod上定义共享存储卷列表 - name: string #共享存储卷名称 (volumes类型有很多种) emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值 hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录 path: string #Pod所在宿主机的目录,将被用于同期中mount的目录 secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部 scretname: string items: - key: string path: string configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部 name: string items: - key: string path: string #小提示: # 在这里,可通过一个命令来查看每种资源的可配置项 # kubectl explain 资源类型 查看某种资源可以配置的一级属性 # kubectl explain 资源类型.