往期回顾: 云端技术驾驭DAY01——云计算底层技术奥秘、云服务器磁盘技术、虚拟化管理、公有云概述 云端技术驾驭DAY02——华为云管理、云主机管理、跳板机配置、制作私有镜像模板 云端技术驾驭DAY03——云主机网站部署、web集群部署、Elasticsearch安装 云端技术驾驭DAY04——Logstash安装部署及插件模块 云端技术驾驭DAY06——容器技术概述、镜像与容器管理、定制简单镜像、容器内安装部署服务 云端技术驾驭DAY07——Dockerfile详解、容器镜像制作、私有仓库 云端技术驾驭DAY08——部署容器服务、Compose微服务管理、harbor仓库部署及管理 云端技术驾驭DAY09——k8s集群安装部署、calico插件部署、计算节点配置管理 云端技术驾驭DAY10——kubectl命令详解、Pod创建过程、Pod的生命周期、定制Pod、资源对象文件 云端技术驾驭DAY11——资源对象文件、Pod自定义命令、多容器Pod、资源监控工具 云端技术驾驭DAY12——Pod调度策略、Pod标签管理、Pod资源配额与限额、全局资源配额与限额策略 云端技术驾驭DAY13——Pod污点、容忍策略、Pod优先级与抢占、容器安全 云端技术驾驭DAY14——存储卷管理、临时卷、持久卷、PV/PVC管理
云端技术驾驭DAY15
服务管理 Service
对外发布应用 服务类型 NodePort服务 Ingress服务 配置Ingress规则
WEB管理工具 Dashboard Dashboard概述 Dashboard安装 发布服务
认证与授权
服务管理
Service
服务原理
容器化带来的问题
自动调度:在Pod创建之前,用户无法预知Pod所在的节点以及Pod的IP地址 一个已经存在的Pod在运行过程中,如果出现故障,Pod也会在新的节点使用新的IP进行部署 应用程序访问服务的时候,地址也不能经常变换 多个相同的Pod如何访问它们上面的服务 Service就是解决这些问题的方法 服务的自动感知
服务会创建一个cluster IP这个地址对应资源地址,不管Pod如何变化,服务总能找到对应的Pod,且cluster IP保持不变 服务的负载均衡
如果服务后端对应多个Pod,则会通过IPTables/LVS规则将访问的请求最终映射到Pod的容器内部,自动在多个容器间实现负载均衡 服务的自动发现
服务创建时会自动在内部DNS上注册域名 域名:<服务名称>.<名称空间>.svc.cluster.local
Cluster IP 服务
Cluster IP 类型
默认的ServiceType,通过集群的内部IP暴露服务,选择该值时服务只能够在集群内部访问
[root@master ~]# vim mysvc.yaml
---
apiVersion: v1
kind: Service # 资源对象类型
metadata:
name: mysvc # 资源对象名称
spec:
ports:
- port: 80 # 监听的端口
protocol: TCP # 协议
targetPort: 80 # 后端服务端口
selector: # 选择算符
app: web # Pod标签
type: ClusterIP # 服务类型
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 7d19h
mysvc ClusterIP 10.245.74.82 <none> 80/TCP 7s
[root@master ~]# dnf -y install bind-utils
[root@master ~]# kubectl -n kube-system get service kube-dns # 查看 DNS 服务地址
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
kube-dns ClusterIP 10.245.0.10 <none> 53/UDP,53/TCP,9153/TCP
[root@master ~]# host mysvc.default.svc.cluster.local 10.245.0.10 # 域名解析测试
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10#53
Aliases:
mysvc.default.svc.cluster.local has address 10.245.74.82
[root@master ~]# vim myweb.yaml # 创建后端应用
---
kind: Pod
apiVersion: v1
metadata:
name: web1
labels:
app: web # 服务靠标签寻找后端
spec:
containers:
- name: apache
image: myos:httpd
[root@master ~]# kubectl apply -f myweb.yaml
pod/web1 created
[root@master ~]# curl 10.245.74.82
Welcome to The Apache.
[root@master ~]# sed 's,web1,web2,' myweb.yaml | kubectl apply -f -
pod/web2 created
[root@master ~]# sed 's,web1,web3,' myweb.yaml | kubectl apply -f -
pod/web3 created
[root@master ~]# curl 10.245.74.82/info.php | grep php_host
php_host: web3
[root@master ~]# curl 10.245.74.82/info.php | grep php_host
php_host: web2
[root@master ~]# curl 10.245.74.82/info.php | grep php_host
php_host: web1
Cluster IP 服务的工作原理
kube-proxy是在所有节点上运行的代理。可以实现简单的数据转发,可以设置更新IPTables/LVS规则,在服务创建时,还提供服务地址DNS自动注册与服务发现功能 使用固定IP
Cluster IP 是随机分配的,如果想使用固定IP,可以自定义,但IP的范围必须符合服务的CIDR 通过kubectl cluster-info dump | grep -i service-cluster-ip-range
查看IP范围
[root@master ~]# vim mysvc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: mysvc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: ClusterIP
clusterIP: 10.245.1.80
[root@master ~]# kubectl delete service mysvc
service "mysvc" deleted
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 7d20h
mysvc ClusterIP 10.245.1.80 <none> 80/TCP 7s
端口别名
当两个作为后端的Pod端口号不一样时,可以使用端口别名
[root@master ~]# vim mysvc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: mysvc
spec:
ports:
- port: 80
protocol: TCP
targetPort: myhttp # 使用别名查找后端服务端口
selector:
app: web
type: ClusterIP
clusterIP: 10.245.1.80
[root@master ~]# vim myweb.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
labels:
app: web
spec:
containers:
- name: apache
image: myos:httpd
ports: # 配置端口规范
- name: myhttp # 声明端口别名
protocol: TCP # 协议
containerPort: 80 # 端口号
[root@master ~]# kubectl delete service mysvc
service "mysvc" deleted
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl apply -f myweb.yaml
pod/web1 created
[root@master ~]# curl 10.245.1.80 # 通过别名和指定IP访问成功
Welcome to The Apache.
对外发布应用
服务类型
发布服务
ClusterIP服务可以解决集群内应用互访的问题,但外部的应用无法访问集群内的资源,某些应用需要访问集群内的资源,我们就需要对外发布服务 服务类型
ClusterIP默认类型可以实现Pod的自动感知与负载均衡,是最核心的服务类型,但ClusterIp不能对外发布服务,如果想对外发布服务可以使用NodePort或Ingress
NodePort服务
NortPort概述
使用基于端口映射(默认值:30000-32767)的方式对外发布服务,可以发布任意服务(四层) 服务资源文件
[root@master ~]# vim mysvc1.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc1
spec:
type: NodePort # 指定服务类型
selector:
app: web
ports:
- protocol: TCP
port: 80
nodePort: 30080 # 可选,不指定则使用随机端口
targetPort: 80
[root@master ~]# kubectl apply -f mysvc1.yaml
service/mysvc1 created
[root@master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 7d21h
mysvc1 NodePort 10.245.238.47 <none> 80:30080/TCP 6m29s
root@master ~]# curl node-0001:30080
Welcome to The Apache.
[root@master ~]# curl node-0002:30080
Welcome to The Apache.
[root@master ~]# curl node-0003:30080
Welcome to The Apache.
[root@master ~]# curl node-0004:30080
Welcome to The Apache.
[root@master ~]# curl node-0005:30080
Welcome to The Apache.
Ingress服务
Ingress概述
使用Ingress控制器(一般由Nginx或HAProxy构成),用来发布http、https服务(七层) Ingress控制器镜像地址:github.com/kubernetes/ingress-nginx Ingress安装
[root@master ingress]# docker load -i ingress.tar.xz # 导入Ingress镜像
[root@master ingress]# docker images|while read i t _;do # 上传镜像
> [[ "${t}" == "TAG" ]] && continue
> [[ "${i}" =~ ^"harbor:443/".+ ]] && continue
> docker tag ${i}:${t} harbor:443/plugins/${i##*/}:${t}
> docker push harbor:443/plugins/${i##*/}:${t}
> docker rmi ${i}:${t} harbor:443/plugins/${i##*/}:${t}
> done
[root@master ingress]# sed -ri 's,^(\s*image: )(.*/)?(.+)@.*,\1harbor:443/plugins/\3,' deploy.yaml # 修改以下三行
458: image: harbor:443/plugins/controller:v1.5.1
565: image: harbor:443/plugins/kube-webhook-certgen:v20220916-gd32f8c343
614: image: harbor:443/plugins/kube-webhook-certgen:v20220916-gd32f8c343
[root@master ingress]# kubectl apply -f deploy.yaml
[root@master ingress]# kubectl label nodes node-0001 ingress-ready="true" # 通过标签指定在那台机器上发布应用
node/node-0001 labeled
[root@master ~]# kubectl -n ingress-nginx get pods
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-bnk2n 0/1 Completed 0 2m12s
ingress-nginx-admission-patch-jsbxh 0/1 Completed 0 2m12s
ingress-nginx-controller-bbbb5f675-m4tck 1/1 Running 0 2m12s
配置Ingress规则
[root@master ~]# kubectl get pods,service
NAME READY STATUS RESTARTS AGE
pod/web1 1/1 Running 1 (31m ago) 3h52m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 8d
service/mysvc ClusterIP 10.245.1.80 <none> 80/TCP 16m
service/mysvc1 NodePort 10.245.209.208 <none> 80:30080/TCP 3h1m
[root@master ~]# curl 10.245.1.80
Welcome to The Apache.
配置规则
资源对象模板:kubectl create ingress mying --class=nginx --rule=nsd.tedu.cn/*=mysvc:80 --dry-run=client -o yaml
[root@master ~]# vim mying.yaml
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: mying
spec:
ingressClassName: nginx # 使用的类名称
rules: # ingress 规则定义
- host: mying.cn # 域名定义,可以不写
http: # 协议
paths: # 访问的路径定义
- path: / # 访问的url路径
pathType: Prefix # 路径的类型[Exact Prefix]
backend: # 后端服务
service: # 服务声明
name: mysvc # 服务名称
port: # 端口号声明
number: 80 # 访问服务的端口号
[root@master ~]# kubectl apply -f mying.yaml
ingress.networking.k8s.io/mying created
[root@master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
mying nginx mying.cn 80 12s
[root@master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
mying nginx mying.cn 192.168.1.51 80 14m
[root@master ~]# curl -H "Host: mying.cn" http://192.168.1.51
Welcome to The Apache.
WEB管理工具
Dashboard
Dashboard概述
Dashboard是什么?
Dashboard是给予网页的Kubernetes用户界面 Dashboard同时展示了Kubernetes集群中的资源状态信息和所有报错信息 可以使用Dashboard将应用部署到集群中,也可以对容器应用排错,还能管理集群资源 地址:github.com/kubernetes/dashboard
Dashboard安装
[root@master dashboard]# docker load -i dashboard.tar.xz
[root@master dashboard]# docker images|while read i t _;do
> [[ "${t}" == "TAG" ]] && continue
> [[ "${i}" =~ ^"harbor:443/".+ ]] && continue
> docker tag ${i}:${t} harbor:443/plugins/${i##*/}:${t}
> docker push harbor:443/plugins/${i##*/}:${t}
> docker rmi ${i}:${t} harbor:443/plugins/${i##*/}:${t}
> done
[root@master dashboard]# sed -ri 's,^(\s*image: )(.*/)?(.+),\1harbor:443/plugins/\3,' recommended.yaml
193: image: harbor:443/plugins/dashboard:v2.7.0
278: image: harbor:443/plugins/metrics-scraper:v1.0.8
[root@master dashboard]# kubectl apply -f recommended.yaml
[root@master dashboard]# kubectl -n kubernetes-dashboard get pods
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-66f6f56b59-trznx 1/1 Running 0 28s
kubernetes-dashboard-65ff57f4cf-7dn87 1/1 Running 0 28s
发布服务
[root@master dashboard]# sed -n '30,45p' recommended.yaml > dashboard-svc.yaml
[root@master dashboard]# vim dashboard-svc.yaml
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort # 添加类型,以NodePort形式发布
ports:
- port: 443
nodePort: 30443 # 指定端口
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
[root@master dashboard]# kubectl apply -f dashboard-svc.yaml
service/kubernetes-dashboard configured
[root@master dashboard]# kubectl -n kubernetes-dashboard get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.245.155.177 <none> 8000/TCP 8m14s
kubernetes-dashboard NodePort 10.245.210.63 <none> 443:30443/TCP 8m14s
添加监听器,前端端口设置为30443,并监听任意一个节点的30443端口 使用弹性公网 IP绑定ELB 发布成功后,通过浏览器访问https://公网IP:30443
,出现如下界面即成功
认证与授权
ServiceAccount
用户概述
用户认证
所有k8s集群都有两类用户:由k8s管理的服务帐号和普通用户 普通用户是以证书或密钥形式签发,主要用途是认证和鉴权,集群中并不包含用来代表普通用户帐号的对象,普通用户的信息无法调用和查询 服务帐号是Kubernetes API所管理的用户。它们被绑定到特定的名称空间,与一组Secret凭据相关联,供Pod调用以获得相应的授权
创建ServiceAccount
[root@master dashboard]# vim admin-user.yaml
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: kube-admin
namespace: kubernetes-dashboard
[root@master dashboard]# kubectl apply -f admin-user.yaml
serviceaccount/kube-admin created
[root@master dashboard]# kubectl -n kubernetes-dashboard get sa
NAME SECRETS AGE
default 0 30m
kube-admin 0 11s
kubernetes-dashboard 0 30m
[root@master dashboard]# kubectl -n kubernetes-dashboard create token kube-admin
eyJhbGciOiJSUzI1NiIsImtpZCI6Im... ... # 这一串字符就是登陆用的token
权限管理
角色与授权
如果想访问和管理k8s集群,就要对身份以及权限做验证,k8s支持的鉴权模块有Node、RBAC、ABAC、Webhook API
Node:专门对kubelet发出的请求进行鉴权 RBAC:是一种基于组织中用户的角色来控制资源使用的方法 ABAC:基于属性的访问控制,是一种通过将用户属性与权限组合在一起向用户授权的方法 Webhook:是一个HTTP回调 查询集群使用的鉴权方法
[root@master dashboard]# kubectl cluster-info dump | grep authorization-mode
"--authorization-mode=Node,RBAC",
RBAC授权
RBAC声明了四种k8s对象:
Role:用来在某一名称空间内创建授权角色,创建Role时,必须指定所属的名称空间的名字 Cluster:可以和Role相同完成授权,但属于集群范围,对所有名称空间有效 RoleBinding:是将角色中定义的权限赋予一个或者一组用户,可以使用Role或ClusterRole完成授权 ClusterRoleBinding:在集群范围执行授权,对所有名称空间有效,只能使用ClusterRole完成授权 资源对象角色与作用域
资源对象 描述 作用域 ServiceAccount 服务账号,为 Pod 中运行的进程提供了一个身份 单一名称空间 Role 角色,包含一组代表相关权限的规则 单一名称空间 ClusterRole 角色,包含一组代表相关权限的规则 全集群 RoleBinding 将权限赋予用户,Role、ClusterRole 均可使用 单一名称空间 ClusterRoleBinding 将权限赋予用户,只可以使用 ClusterRole 全集群
create delete deletecollection get list patch update watch 创建 删除 删除集合 获取属性 获取列表 补丁 更新 监控
# 资源对象模板
[root@master ~]# kubectl -n default create role myrole --resource=pods --verb=get,list --dry-run=client -o yaml
[root@master ~]# kubectl -n default create rolebinding kube-admin-role --role=myrole --serviceaccount=kubernetes-dashboard:kube-admin --dry-run=client -o yaml
[root@master ~]# vim myrole.yaml
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: myrole # 角色名称
namespace: default
rules: # 规则
- apiGroups: # 资源对象所属组信息
- "" # 分组信息
resources: # 要设置权限的资源对象
- pods # 授权资源对象名称
verbs: # 权限设置
- get # 权限
- list # 权限
... ... # 接着上面的写
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kube-admin-role # 授权策略名称
namespace: default
roleRef: # 关联权限
apiGroup: rbac.authorization.k8s.io # 角色对象组
kind: Role # 角色对象
name: myrole # 角色名称
subjects: # 授权信息
- kind: ServiceAccount # 帐号资源对象
name: kube-admin # 帐号名称
namespace: kubernetes-dashboard # 帐号所在的名称空间
[root@master dashboard]# kubectl apply -f myrole.yaml
role.rbac.authorization.k8s.io/myrole created
rolebinding.rbac.authorization.k8s.io/kube-admin-role created
... ...
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kube-admin-role
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kube-admin
namespace: kubernetes-dashboard
[root@master dashboard]# kubectl apply -f myrole.yaml
role.rbac.authorization.k8s.io/myrole created
clusterrolebinding.rbac.authorization.k8s.io/kube-admin-role created
授予管理员权限后,再次登陆Dashboard可以管理集群信息