K8S 在有赞 PaaS 测试环境中的实践
文 | 侯枝影 on 测试
一、背景介绍
2.1 公司持续交付系统不支持 PaaS 产品
2.2 成本问题
2.2.1 资源成本
2.2.2 部署成本
2.2.3 顺势而为
二、整体架构
我们的目标是要解决持续集成和持续测试快速、低成本、自动化的问题,整个架构由 Gitlab + Jenkins + Harbor + Kubernetes 集成。
三、操作步骤
3.1 K8S 与 jenkins 集成
podTemplate(label: 'mypod', cloud: 'kubernetes',containers: [
containerTemplate(
name: 'jnlp',
image: 'www.harbor.com/yzcontainer/yz-centos-jnlp-slave:latest',
alwaysPullImage: true,
args: '${computer.jnlpmac} ${computer.name}',
env:['name':'application_standard_env','value':'daily']
),
],
volumes: [
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
]){
node('mypod') {
stage('test') {
container('jnlp') {
sh """
"""
}
}
}
}
以上脚本中有几个地方需要变更:
image 值为基础镜像,需要定制化,比如应用运行的操作系统、编译打包运行依赖的软件等等; sh 编写我们需要执行的命令,比如 clone 代码、编译、打包、打镜像、push 镜像到公司仓库等。
3.2 创建 Namespace
命令行直接创建
kubectl create namespace namespace名称 //namespace 可以简写成 ns
通过文件创建
定义 my-namespace.yaml 文件
apiVersion: v1
kind: Namespace
metadata:
name: namespace名称
命令行创建
kubectl create -f ./my-namespace.yaml
kubectl get ns
命令查看所有 Namespace。3.3 创建 Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: //自定义标签名称
name: //deploy名称,推荐跟应用名一致
namespace: //deploy所属的命名空间
spec:
progressDeadlineSeconds: 600
replicas: 1 //通过增加副本数来弹缩应用,有多少个副本数就有多少个pod
revisionHistoryLimit: 10
selector:
matchLabels:
run: //自定义标签名称
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: //自定义标签名称
spec:
containers:
- image: //容器的镜像名称
imagePullPolicy: Always
name://容器名称,推荐跟应用名一致
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
kubectl create/apply -f xxx.yaml
$ kubectl get pod -n [namepsace] -o wide
NAME READY STATUS RESTARTS AGE IP NODE
301mock-6cf74454f7-794l2 1/1 Running 0 5s x.x.x.x x.x.x.x
kubectl logs -f [pod name] -n [namepsace]
查看日志定位失败原因。kubectl exec -it [pod name] bash -n [namespace]
进入容器内部,其他操作同 linux 下。kubectl delete pod [pod name] -n [namespace]
,Kube-controller-manager 会重新创建 Pod 使集群状态符合 deployment 中定义的预期状态。3.4 创建 Service
kubectl expose deploy/etcd --port=2379 --target-port=2379 --name=etcd --type=NodePort -n [namespace]
通过文件创建
定义 my-service.yaml 文件
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace:
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 2379
targetPort: 2379
type: NodePort
命令行创建
kubectl create -f my-service.yaml
kubectl get svc -n [namespace]
命令查看。kubectl get svc -n [namespace]
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
etcd NodePort 10.99.127.115 <none> 2379:31422/TCP 4d run=etcd
现在我们就可以通过 CLUSTER-IP:2379 访问集群内部服务了。
4.1 NodeName
spec:
containers:
- image:
imagePullPolicy: Always
name:
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
nodeName: x.x.x.x
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
4.2 SecurityContext
spec:
containers:
- image:
imagePullPolicy: Always
name: tsp-worker
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
4.3 Volumes
spec:
containers:
- image:
imagePullPolicy: Always
name: etcd
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /default.etcd //容器内的目录
name: etcd-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /data/etcd //挂载到宿主机上的目录
type: Directory
name: etcd-volume
4.4 Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: yz7-ingress
namespace: yz7
spec:
rules:
- host: yz7-test-control.s.yz.com
http:
paths:
- backend:
serviceName: yz7-cluster
servicePort: 8888
path: /
kubectl create -f ingress.yaml
查看 Ingress:
kubectl get ing -n yz7 -o wide
NAME HOSTS ADDRESS PORTS AGE
yz7-ingress x.x.x.x x.x.x.x 80 25d
4.5 DNS
普通的 Service,会生成 servicename.namespace.svc.cluster.local 的域名,解析到 Service 对应的 ClusterIP 上,在 Pod 之间的调用可以简写成 servicename.namespace,如果处于同一个命名空间下面,甚至可以只写成 servicename 即可访问;
Headless Service,就是把 clusterIP 设置为 None 的服务,会被解析为指定 Pod 的 IP 列表,通过 podname.servicename.namespace.svc.cluster.local 访问到具体的某一个 Pod。
五、结束语
相关阅读
-The End-
Vol.222
有赞技术团队
为 442 万商家,150 个行业,330 亿电商交易额
提供技术支持
微商城|零售|美业 | 教育
微信公众号:有赞coder 微博:@有赞技术
技术博客:tech.youzan.com
The bigger the dream,
the more important the team