我司项目现在跑在阿里云的ACK上,用到的语言有php(主力语言)、golang、python、c#,一共跑了十来个微服务,扛过了好几次的大流量,目前生产环境也稳定运行了两年多了。最近因为要离职了,所以完整地回顾一下整个流程,后面有可能还会更新其他的一些东西,权当是做个记录吧~
更新日志
- 2022-09-23 init
前期准备
- gitlab:用于代码仓库和CI/CD
- 阿里云ACK:托管版的kubernetes(1.22.10)
- 阿里云镜像仓库:用于托管镜像
开始
先定义项目名称为 myapp
,所有用户名都为 sellmoe
创建镜像仓库
在阿里云容器镜像服务中,创建一个仓库 myapp_base
和 myapp
,类型都设为私有
构建基础镜像
- 为了避免后面ci/cd中update和安装扩展带来的时间浪费,所以做一个基于php8.0的基础镜像很有必要,如果还有其他项目,完全可以复用
- 首先咱们用命令在本地拉取laravel的代码
laravel new myapp
- 在根目录下新建一个
Dockerfile_Base
文件,构建一个基础镜像
FROM php:8.0-fpm
MAINTAINER sellmoe
RUN apt-get update
RUN apt-get install -y libmcrypt-dev libonig-dev zlib1g-dev libpng-dev libzip-dev zip && pecl install mcrypt-1.0.4
RUN docker-php-ext-enable mcrypt \
&& docker-php-ext-install \
pdo \
pdo_mysql \
mbstring \
pcntl \
opcache \
bcmath \
gd \
zip
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN sed -i 's/disable_functions =/disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,popen,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru/' /usr/local/etc/php/php.ini
RUN sed -i 's/;date.timezone =/date.timezone = PRC/' /usr/local/etc/php/php.ini
RUN sed -i 's/;opcache.enable=1/opcache.enable=1/' /usr/local/etc/php/php.ini
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
然后用 docker build -f Dockerfile_Base -t registry.cn-hongkong.aliyuncs.com/sellmoe/myapp_base:release .
构建好基础镜像
最后推送到容器镜像仓库 docker push registry.cn-hongkong.aliyuncs.com/sellmoe/myapp_base:release
构建主项目镜像
还是laravel根目录新建Dockerfile,以基础镜像为基础,把代码拷贝进去
FROM registry.cn-hongkong.aliyuncs.com/sellmoe/myapp_base:release
MAINTAINER sellmoe
COPY ./ /var/www/html/
EXPOSE 9000
k8s部署文件
一般k8s部署的文件都得新开一个git项目,我们把所有的相关yaml文件全部放到这个项目中
ConfigMap: laravel的.env
新建一个configmap-laravel.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cvs-config
data:
.env: |
APP_NAME=MyApp
APP_ENV=production
...
ConfigMap: nginx配置文件
新建一个configmap-nginx.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
site.conf: |
server {
listen 80;
server_name myapp.test;
location / {
try_files uriuri/ /index.php?args;
}
location ~ \.php {
root /var/www/html/public;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
Deployment: nginx
新建一个deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: nginx
tier: backend
template:
metadata:
name: nginx
labels:
app: nginx
tier: backend
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
name: http
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 15
tcpSocket:
port: 80
timeoutSeconds: 30
readinessProbe:
initialDelaySeconds: 15
periodSeconds: 30
tcpSocket:
port: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d/
name: nginx-config
readOnly: true
volumes:
- name: nginx-config
configMap:
defaultMode: 420
name: nginx-config
Deployment: php
新建一个deployment-php.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php
labels:
tier: backend
spec:
replicas: 1
minReadySeconds: 3 #Pod就绪/可用后的时间
revisionHistoryLimit: 6 #保留的旧副本数量,方便回滚到上一个版本:kubectl rollout undo deployment.v1.apps/DEPLOY_NAME
strategy: #滚动更新策略,Recreate:先杀Pods,再创建;RollingUpdate:滚动更新
type: RollingUpdate
rollingUpdate:
maxSurge: 1 #最大峰值,可是绝对值或百分比(默认25%),用来指定可以创建的超出期望 Pod 个数的 Pod 数量。比如30%表示新旧pod数量不超过130%
maxUnavailable: 50% #更新中不可用Pod的个数上限,可是绝对值或百分比(默认25%)
selector:
matchLabels:
app: php #与下面template中对应
tier: backend
template:
metadata:
name: php
labels:
app: php
tier: backend
spec:
#affinity: #亲和性
# podAntiAffinity: #podAffinity:pod亲和性,podAntiAffinity:pod反亲和性
# preferredDuringSchedulingIgnoredDuringExecution: #软策略:最好满足,与之相对的赢策略requiredDuringSchedulingIgnoredDuringExecution表示一定满足
# - podAffinityTerm: #匹配策略
# labelSelector:
# matchExpressions:
# - key: app
# operator: In
# values:
# - backend
# topologyKey: kubernetes.io/hostname
# weight: 100
initContainers: #初始化容器,在所有pod前运行,用于运行镜像中不存在的工具和脚本。kubelet会一直尝试运行直到成功,如果pod的restartPolicy是Never,那么只尝试一次,会标记pod失败
- name: artisan #初始化容器名,可通过kubectl logs POD_NAME -c init容器名查看日志
image: registry.cn-hongkong.aliyuncs.com/sellmoe/myapp:release
imagePullPolicy: Always
envFrom: #.env文件先挂载,直接可以拷贝到共享volume中,下面的就不需要挂载了
- configMapRef:
name: cvs-config
args:
- /bin/bash
- -c
- (php artisan migrate || true) && (php artisan config:cache || true) && (php
artisan route:cache || true) && (cp -rp /var/www/html /codebase)
volumeMounts: #init容器先把代码拷贝到共享volume中
- mountPath: /codebase
name: codebase
containers:
- name: php
image: registry.cn-hongkong.aliyuncs.com/sellmoe/myapp:release
imagePullPolicy: Always
ports: #暴露的端口
- containerPort: 9000
protocol: TCP
livenessProbe: #存活探测器
failureThreshold: 3
initialDelaySeconds: 15 #第一次探测前延迟的秒数
periodSeconds: 10 #每次探测间隔秒数
successThreshold: 1
tcpSocket: #表示用tcp套接字来检测存活状态
port: 9000
timeoutSeconds: 1
readinessProbe: #就绪探测器
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 9000
timeoutSeconds: 1
resources: #资源限制
limits:
cpu: 200m
memory: 400M
requests:
cpu: 100m
memory: 200M
volumeMounts:
- mountPath: /var/www/
name: codebase
lifecycle:
postStart:
exec:
command: [ "/bin/sh", "-c", "chmod 777 -R storage && chmod 777 -R bootstrap/cache" ]
volumes: #共享代码volume(app和initContainer)
- name: codebase
emptyDir: {}
imagePullSecrets:
- name: regsecret #拉取镜像的secret
Service: nginx
新建一个文件service-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
tier: backend
spec:
selector:
app: nginx
tier: backend
ports:
- protocol: TCP
port: 80
targetPort: 80
Service: php
新建一个service-php.yaml
apiVersion: v1
kind: Service
metadata:
name: php
labels:
tier: backend
spec:
selector:
app: php
tier: backend
ports:
- port: 9000
protocol: TCP
gitlab配置
因为私有gitlab拉取私有仓库的镜像是需要认证的,所以我们先获取阿里云拉取docker镜像的auth
echo -n "阿里云用户名:阿里云密码" | base64
然后到gitlab对应项目中,把下面这段配置到CI/CD的variables中,key可以是ALIYUN_AUTH_CONFIG
{
"auths": {
"仓库地址,如:registry.cn-hongkong.aliyuncs.com": {
"auth": "上一步生成的auth config"
}
}
}
.gitlab-ci.yaml
在项目根目录下新建 .gitlab-ci.yaml
文件
stages:
- deploy
deploy:
stage: deploy
image: docker:dind #docker in docker
tags:
- docker
only:
- master
script:
- mkdir ~/.docker
- echo ${ALIYUN_AUTH_CONFIG} > ~/.docker/config.json
- docker build -f Dockerfile -t registry.cn-hongkong.aliyuncs.com/sellmoe/myapp:release .
- docker push registry.cn-hongkong.aliyuncs.com/sellmoe/myapp:release
配置推送镜像自动触发重新部署
因为我们推送了镜像,但是并没有让k8s滚动更新,所以在阿里云容器服务控制台选择无状态 - php
触发器,创建一个重新部署的触发器,然后把触发器链接复制到容器镜像服务对应镜像仓库的触发器中
这篇文章还没有评论