服务的管理与权限
#### 一、服务管理——对内发布

##### 测试自动感知
```shell
# 创建clusterIP和Pod
kubectl apply -f websvc.yml -f web.yml
# 查看创建详情
kubectl get service
kubectl get pods
# 验证ip转发
curl http://...
```

测试文件
```yaml
# websvc.yml
---
kind: Service
apiVersion: v1
metadata:
name: websvc
spec:
type: ClusterIP
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
#---------------------------------------------------------------------
# web.yml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
labels:
app: web
spec:
containers:
- name: apache
image: myos:httpd
```
##### 测试负载均衡
```shell
# 创建多个Pod做对比测试
kubectl apply -f web.yml
sed 's,web1,web2,' web.yml | kubectl apply -f -
sed 's,web1,web3,' web.yml | kubectl apply -f -
# 查看创建详情
kubectl get pods
# 访问测试负载均衡
curl http://...
```

测试使用自动感知文件,不用改动
##### 测试域名解析
```shell
#
kubectl -n kube-system get service kube-dns
#
host websvc.default.svc.cluster.local [CLUSTER-IP]
```
##### 固定IP服务
使创建的服务固定IP,不论服务重建多少次
```shell
# 修改配置,在spec级下添加子项clusterIP
ip地址选取范围在文件中声明,或者通过命令查找
kubectl cluster-info dump | grep ip-range
# 创建服务验证端口
kubectl replace --force -f websvc.yml
kubectl get service
```

测试文件
```yaml
# websvc.yml
---
kind: Service
apiVersion: v1
metadata:
name: websvc
spec:
type: ClusterIP
clusterIP: 10.245.1.80
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
```
##### 端口别名
```shell
# 修改websvc.yml的端口别名
sed -i "s,targetPort: 80$,targetPort: myhttp," websvc.yml
# 重置Pod与服务
kubectl replace --force -f websvc.yml
kubectl apply -f web.yml
# 访问测试
curl http://10.245.1.82
```

测试文件
```yaml
# web.yml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
labels:
app: web
spec:
containers:
- name: apache
image: myos:httpd
ports:
- name: myhttp
protocol: TCP
containerPort: 80
```
> 报错检查目标:服务标签、端口别名、ip
#### 二、服务管理——对外发布

##### nodePort(四层)
基于端口映射方式对外发布服务
```shell
# 添加服务类型以及端口映射启服务
kubectl apply -f mysvc.yml
# 查看服务状态
kubectl get service
# 访问节点映射端口测试Pod服务
curl http://node-0001:30080
```
测试文件
```yaml
# mysvc.yml
---
kind: Service
apiVersion: v1
metadata:
name: nodesvc
spec:
type: NodePort
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80
nodePort: 30080
targetPort: myhttp
```
##### ingress(七层)
ingress公开集群外部访问的http/https路由,只是一个代理所以依赖后端服务
> 获取控制器镜像及资源文件
> https://github.com/kubernetes/ingress-nginx
```shell
## 安装控制器
# 导入镜像
docker load -i ingress.tar.xz
# 上传镜像
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
# 修改镜像
sed -ri 's,^(\s*image: )(.*/)?(.+),\1harbor:443/plugins/\3,' deploy.yaml
# 运行清单,启动服务
kubectl apply -f deploy.yaml
kubectl -n ingress-nginx get pods
# 查看Pod及服务
kubectl get pods,services
# 访问测试
curl http://10.245.1.80
## 对外发布
# 查看控制器类
kubectl get ingressclasses.networking.k8s.io
# 通过模板创建资源清单文件
kubectl create ingress myingress --class=nginx --rule=nsd.tedu.cn/*=mysvc:80 --dry-run=client -o yaml > myingress.yml
# 启动控制器
kubectl apply -f mying.yaml
kubectl get ingress
# 测试服务手动解析域名
curl -H "Host: nwuniv.edu.cn" http://192.168.88.51
```

测试文件
```yaml
# myingress.yml
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: myingess
spec:
ingressClassName: nginx #类型名指定控制器,使用get ingressclass查找
rules: #规则策略,七层域名+url
- host: nwuniv.edu.cn #定义域名,请求来源,不能包含大写会报错
http: #
paths:
- path: / #定义路径
pathType: Prefix #路径类型,Prefix宽松模式能访问路径下所有子目录 | Exact严格模式只能访问目标目录子目录和文件无法访问
backend: #定义后端,请求转发
service: #定义服务
name: websvc #定义服务名
port: #服务端口号
number: 80
```
#### 三、Dashboard插件与服务权限
> 服务使用443端口需要证书,而ingress需要设置证书步骤繁琐所以不做测试,暂时挖坑有机会待补,只使用NodePort做测试
这是基于网页的kubernetes界面,通过浏览器管理k8s集群,将容器运行、管理资源、报错排错等操作可视化
dashboard官网地址:https://github.com/kubernetes/dashboard
##### 插件安装
```shell
## 安装插件
# 导入镜像并上传仓库
docker load -i dashboard.tar.xz
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
# 修改地址
sed -ri 's,^(\s*image: )(.*/)?(.+),\1harbor:443/plugins/\3,' recommended.yaml
# 启服务
kubectl apply -f recommended.yaml
kubectl -n kubernetes-dashboard get pods
## 发布服务
# 查看服务状态
kubectl -n kubernetes-dashboard get service
# 获取服务资源对象文件
sed -n '30,45p' recommended.yaml > dashboard.yml
# 启动dashboard
kubectl apply -f dashboard.yml
kubectl -n kubernetes-dashboard get service
# 通过浏览器访问Dashboard登录页面
## 创建服务账号
# 获取资源对象模板
kubectl create serviceaccount kube-admin --dry-run=client -o yaml > admin.yml
# 创建用户
kubectl apply -f admin.yml
# 查看用户信息
kubectl -n kubernetes-dashboard get serviceaccounts
# 获取用户token用于登录dashboard
kubectl -n kubernetes-dashboard create token kube-admin
# 获取到令牌数据粘贴到浏览器登入
```
> 登录右上角有用户细节描述表示登录成功
>
> 
测试文件
```yaml
# dashboard.yml
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
nodePort: 30443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
```
##### 鉴权、角色与授权
集群支持的鉴权模块有四种:
Node:特殊用途的鉴权模式
RBAC:企业级授权,基于列表属性的访问模块
ABAC:基于属性的访问模块
Webhook:开发专用
RBAC声明了四种集群资源对象:
Role、ClusterRole、RoleBinding、ClusterRoleBinding
| 资源对象 | 描述 | 作用域 |
| ------------------ | ----------------------------------------- | ------------ |
| ServiceAccount | 服务帐号,为Pod中运行的进程提供一个身份 | 唯一名称空间 |
| Role | 角色,包含一组代表相关权限的规则 | 唯一名称空间 |
| ClusterRole | 角色,包含一组代表相关权限的规则 | 全集群 |
| RoleBinding | 将权限赋予用户,Role、ClusterRole均可使用 | 唯一名称空间 |
| ClusterRoleBinding | 将权限赋予用户,仅ClusterRole可使用 | 全集群 |
资源对象权限:craete(创建)、delete(删除)、deletecolltction(删除集合)、get(获取属性)、list(列表)、patch(补丁)、update(更新)、watch(监控)
```shell
## 集群普通用户
# 查询集群鉴权方法
kubectl cluster-info dump | grep authorization-mode
# 通过模板获取资源对象模板
kubectl -n default create role myrole --resource=pods --verb=get,list --dry-run=client -o yaml > myrole.yml
kubectl -n default create rolebinding kube-admin-role --role=myrole --serviceaccount=kubernetes-dashboard:kube-admin --dry-run=client -o yaml >> myrole.yml
# 启动测试
kubectl apply -f myrole.yml
# 清空实验
kubectl delete -f myrole.yml
## 集群管理员
# 查看集群角色
kubectl get clusterrole
# 获取资源对象模板
kubectl create clusterrolebinding kube-admin-role --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kube-admin --dry-run=client -o yaml >> myrole.yml
# 启动管理员角色,进入浏览器测试
kubectl apply -f myrole.yml
# 浏览器可视化交互操作过于无脑不做演示
```

测试文件
```yaml
# myrole.yml
---
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
# 普通用户操作↑
#---------------------------------------------------------------------
# 管理员操作↓
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kube-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kube-admin
namespace: kubernetes-dashboard
```