要进行分环境,需要将现有实验环境进行拆分

portal服务,可以各个环境共用,但是apollo-adminservice和apollo-configservice必须要分开。

1、zk环境拆分为test和prod环境

添加dns解析:

# vi /var/named/od.com.zone

zk-test.od.com       A       10.4.7.11

zk-prod.od.com      A       10.4.7.12

2、namespace 分环境,创建test 和prod

# kubectl create ns test
# kubectl create ns prod

创建secret:

# kubectl create secret docker-registry harbor --docker-server=harbor.od.com --docker-username=harbor --docker-password=Harbor12345 -n test

# kubectl create secret docker-registry harbor --docker-server=harbor.od.com --docker-username=harbor --docker-password=Harbor12345 -n prod

3、数据库进行拆分,因实验资源有限,故使用分库的形式模拟分环境

修改数据库初始化脚本,分别创建ApolloConfigTestDB和ApolloConfigProdDB

修改数据库中eureka的地址,这里用到了两个新的域名,自行在bind9中添加解析

> update ApolloConfigProdDB.ServerConfig set ServerConfig.Value="http://config-prod.od.com/eureka" where ServerConfig.Key="eureka.service.url";

> grant INSERT,DELETE,UPDATE,SELECT on ApolloConfigProdDB.* to "apolloconfig"@"10.4.7.%" identified by "123456";

> update ApolloConfigTestDB.ServerConfig set ServerConfig.Value="http://config-test.od.com/eureka" where ServerConfig.Key="eureka.service.url";

> grant INSERT,DELETE,UPDATE,SELECT on ApolloConfigTestDB.* to "apolloconfig"@"10.4.7.%" identified by "123456";

修改portal数据,支持fat和pro环境:

> update ServerConfig set Value='fat,pro' where Id=1;

修改portal的cm资源配置清单:

# vi /data/k8s-yaml/apollo-portal/cm.yaml

# kubectl apply -f http://k8s-yaml.od.com/apollo-portal/cm.yaml

分别创建修改两个环境的资源配置文件:

test:

# cd /data/k8s-yaml
# mkdir -p test/{apollo-adminservice,apollo-configservice,dubbo-demo-server,dubbo-demo-consumer}

# mkdir -p prod/{apollo-adminservice,apollo-configservice,dubbo-demo-server,dubbo-demo-consumer}

将之前的资源配置清单cp到对应环境的目录中,进行修改:

# cd  test/apollo-configservice/
# cp ../../apollo-configservice/* ./

1、cm.yaml 修改ns,数据库库名,eureka地址

apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-configservice-cm
namespace: test
data:
application-github.properties: |
# DataSource
spring.datasource.url = jdbc:mysql://mysql.od.com:3306/ApolloConfigTestDB?characterEncoding=utf8
spring.datasource.username = apolloconfig
spring.datasource.password = 123456
eureka.service.url = http://config-test.od.com/eureka
app.properties: |
appId=100003171

2、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: apollo-configservice
namespace: test
labels:
name: apollo-configservice
spec:
replicas: 1
selector:
matchLabels:
name: apollo-configservice
template:
metadata:
labels:
app: apollo-configservice
name: apollo-configservice
spec:
volumes:
- name: configmap-volume
configMap:
name: apollo-configservice-cm
containers:
- name: apollo-configservice
image: harbor.od.com/infra/apollo-configservice:v1.5.1
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: configmap-volume
mountPath: /apollo-configservice/config
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

3、svc.yaml

kind: Service
apiVersion: v1
metadata:
name: apollo-configservice
namespace: test
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: apollo-configservice

4、ingress.yaml

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: apollo-configservice
namespace: test
spec:
rules:
- host: config-test.od.com
http:
paths:
- path: /
backend:
serviceName: apollo-configservice
servicePort: 8080

服务已经注册进来了

接下来部署apollo-adminservice

修改apollo-adminservice的资源配置清单:

# cd /data/k8s-yaml/test/apollo-adminservice
# cp ../../apollo-adminservice/* ./

1、cm.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-adminservice-cm
namespace: test
data:
application-github.properties: |
# DataSource
spring.datasource.url = jdbc:mysql://mysql.od.com:3306/ApolloConfigTestDB?characterEncoding=utf8
spring.datasource.username = apolloconfig
spring.datasource.password = 123456
eureka.service.url = http://config-test.od.com/eureka
app.properties: |
appId=100003172

2、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: apollo-adminservice
namespace: test
labels:
name: apollo-adminservice
spec:
replicas: 1
selector:
matchLabels:
name: apollo-adminservice
template:
metadata:
labels:
name: apollo-adminservice
spec:
volumes:
- name: configmap-volume
configMap:
name: apollo-adminservice-cm
containers:
- name: apollo-adminservice
image: harbor.od.com/infra/apollo-adminservice:v1.5.1
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: configmap-volume
mountPath: /apollo-adminservice/config
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/test/apollo-adminservice/cm.yaml
# kubectl apply -f http://k8s-yaml.od.com/test/apollo-adminservice/dp.yaml

接下来部署prod环境的apollo-configservice,还是一样的套路:

# cd ../../prod/apollo-configservice/
# cp ../../apollo-configservice/* ./

修改资源配置清单:

1、cm.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-configservice-cm
namespace: prod
data:
application-github.properties: |
# DataSource
spring.datasource.url = jdbc:mysql://mysql.od.com:3306/ApolloConfigProdDB?characterEncoding=utf8
spring.datasource.username = apolloconfig
spring.datasource.password = 123456
eureka.service.url = http://config-prod.od.com/eureka
app.properties: |
appId=100003171

2、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: apollo-configservice
namespace: prod
labels:
name: apollo-configservice
spec:
replicas: 1
selector:
matchLabels:
name: apollo-configservice
template:
metadata:
labels:
app: apollo-configservice
name: apollo-configservice
spec:
volumes:
- name: configmap-volume
configMap:
name: apollo-configservice-cm
containers:
- name: apollo-configservice
image: harbor.od.com/infra/apollo-configservice:v1.5.1
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: configmap-volume
mountPath: /apollo-configservice/config
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

3、svc.yaml

kind: Service
apiVersion: v1
metadata:
name: apollo-configservice
namespace: prod
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: apollo-configservice

4、ingress.yaml

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: apollo-configservice
namespace: prod
spec:
rules:
- host: config-prod.od.com
http:
paths:
- path: /
backend:
serviceName: apollo-configservice
servicePort: 8080

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-configservice/cm.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-configservice/dp.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-configservice/svc.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-configservice/ingress.yaml

修改apollo-adminservice的资源配置清单:

# cd ../apollo-adminservice/
# cp ../../apollo-adminservice/* ./

1、cm.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-adminservice-cm
namespace: prod
data:
application-github.properties: |
# DataSource
spring.datasource.url = jdbc:mysql://mysql.od.com:3306/ApolloConfigProdDB?characterEncoding=utf8
spring.datasource.username = apolloconfig
spring.datasource.password = 123456
eureka.service.url = http://config-prod.od.com/eureka
app.properties: |
appId=100003172

2、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: apollo-adminservice
namespace: prod
labels:
name: apollo-adminservice
spec:
replicas: 1
selector:
matchLabels:
name: apollo-adminservice
template:
metadata:
labels:
name: apollo-adminservice
spec:
volumes:
- name: configmap-volume
configMap:
name: apollo-adminservice-cm
containers:
- name: apollo-adminservice
image: harbor.od.com/infra/apollo-adminservice:v1.5.1
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: configmap-volume
mountPath: /apollo-adminservice/config
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-adminservice/cm.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/apollo-adminservice/dp.yaml

两个服务都已经注册进来了,删除portal数据库中存储的关于之前项目的配置,接下来启动portal项目:

# mysql -uroot -p
> use ApolloPortalDB ;
> truncate table App;
> truncate table AppNamespace;

打开portal.od.com验证,并且创建两个项目:

首先创建dubbo-demo-service

添加配置:两个环境都添加上:注意连接地址一个是test.od.com,一个是prod.od.com

接下来创建dubbo-demo-web项目:同样是两个环境都发布,注意一个是test.od.com,一个是prod.od.com

接下来交付dubbo服务分环境交付:

同样操作,修改之前项目的资源配置清单:

# cd /data/k8s-yaml/test/dubbo-demo-server
# cp ../../dubbo-server/* ./

1、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-service
namespace: test
labels:
name: dubbo-demo-service
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-service
template:
metadata:
labels:
app: dubbo-demo-service
name: dubbo-demo-service
spec:
containers:
- name: dubbo-demo-service
image: harbor.od.com/app/dubbo-demo-service:apollo_191211_1916
ports:
- containerPort: 20880
protocol: TCP
env:
- name: C_OPTS
value: -Denv=fat -Dapollo.meta=http://config-test.od.com
- name: JAR_BALL
value: dubbo-server.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-server/dp.yaml

接下来交付dubbo-demo-consumer:

# cd /data/k8s-yaml/test/dubbo-demo-consumer
# cp ../../dubbo-consumer/* ./

1、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: test
labels:
name: dubbo-demo-consumer
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-consumer
template:
metadata:
labels:
app: dubbo-demo-consumer
name: dubbo-demo-consumer
spec:
containers:
- name: dubbo-demo-consumer
image: harbor.od.com/app/dubbo-demo-web:apollo_191212_1715
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 20880
protocol: TCP
env:
- name: C_OPTS
value: -Denv=fat -Dapollo.meta=http://config-test.od.com
- name: JAR_BALL
value: dubbo-client.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

2、svc.yaml

kind: Service
apiVersion: v1
metadata:
name: dubbo-demo-consumer
namespace: test
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-demo-consumer

3、ingress.yaml

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: test
spec:
rules:
- host: demo-test.od.com
http:
paths:
- path: /
backend:
serviceName: dubbo-demo-consumer
servicePort: 8080

这里会用到两个新的域名,添加解析:

应用test环境的dubbo-consumer资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-consumer/dp.yaml
# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-consumer/svc.yaml
# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-consumer/ingress.yaml

接下来交付prod环境的dubbo-demo-server和dubbo-demo-consumer服务:

同样套路,复制资源配置清单,然后修改成prod环境:

cd /data/k8s-yaml/prod/dubbo-demo-server
# cp ../../dubbo-server/* ./

1、dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-service
namespace: prod
labels:
name: dubbo-demo-service
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-service
template:
metadata:
labels:
app: dubbo-demo-service
name: dubbo-demo-service
spec:
containers:
- name: dubbo-demo-service
image: harbor.od.com/app/dubbo-demo-service:apollo_191211_1916
ports:
- containerPort: 20880
protocol: TCP
env:
- name: C_OPTS
value: -Denv=pro -Dapollo.meta=http://config-prod.od.com
- name: JAR_BALL
value: dubbo-server.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/prod/dubbo-demo-server/dp.yaml

接下来做dubbo-demo-consumer的资源配置清单:

# cd /data/k8s-yaml/prod/dubbo-demo-consumer
# cp ../../dubbo-consumer/* ./

1、dp.yaml   http://apollo-configservice:8080  这里可以直接使用svc资源名称调用,不用走ingress,因为svc资源只在当前namespace中生效。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: prod
labels:
name: dubbo-demo-consumer
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-consumer
template:
metadata:
labels:
app: dubbo-demo-consumer
name: dubbo-demo-consumer
spec:
containers:
- name: dubbo-demo-consumer
image: harbor.od.com/app/dubbo-demo-web:apollo_191212_1715
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 20880
protocol: TCP
env:
- name: C_OPTS
value: -Denv=pro -Dapollo.meta=http://apollo-configservice:8080
- name: JAR_BALL
value: dubbo-client.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600

2、svc.yaml

kind: Service
apiVersion: v1
metadata:
name: dubbo-demo-consumer
namespace: prod
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-demo-consumer

3、ingress.yaml

kind: Service
apiVersion: v1
metadata:
name: dubbo-demo-consumer
namespace: prod
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-demo-consumer
[root@hdss7-200 dubbo-demo-consumer]# cat ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: prod
spec:
rules:
- host: demo-prod.od.com
http:
paths:
- path: /
backend:
serviceName: dubbo-demo-consumer
servicePort: 8080

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/prod/dubbo-demo-consumer/dp.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/dubbo-demo-consumer/svc.yaml
# kubectl apply -f http://k8s-yaml.od.com/prod/dubbo-demo-consumer/ingress.yaml

访问两个环境的不同url:

http://demo-test.od.com

http://demo-prod.od.com

模拟发版:

使用jenkins构建新的镜像:

构建成功,然后我们在测试环境发布此版本镜像:

修改测试环境的dp.yaml

应用修改后的资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-consumer/dp.yaml

已经成功将新代码上线到test环境,接下来上线到prod环境

同样修改prod环境的dp.yaml,并且应用该资源配置清单:

已经上线到生产环境,这样一套完整的分环境使用apollo配置中心发布流程已经可以使用了,并且真正做到了一次构建,多平台使用。

kubernetes实战-配置中心(四)分环境使用apollo配置中心的更多相关文章

  1. kubernetes实战-配置中心(二)交付apollo配置中心到k8s

    apollo官网:官方地址 apollo架构图: apollo需要使用数据库,这里使用mysql,注意版本需要在5.6以上: 本次环境mysql部署在10.4.7.11上,使用mariadb:10.1 ...

  2. kubernetes实战之consul简单测试环境搭建及填坑

    这一节内容有点长,我们将介绍如何基于docker搭建一client一server的consul测试环境,以及如何搭建多server consul测试集群.在基于docker搭建多server的cons ...

  3. K8S(12)配置中心实战-多环境交付apollo三组件

    k8s配置中心实战-多环境交付apollo三组件 目录 k8s配置中心实战-多环境交付apollo三组件 1.环境准备工作 1.1 zk环境拆分 1.2 namespace分环境 1.3 数据库拆分 ...

  4. 【第十四章】 springboot + profile(不同环境读取不同配置)

    具体做法: 不同环境的配置设置一个配置文件,例如:dev环境下的配置配置在application-dev.properties中:prod环境下的配置配置在application-prod.prope ...

  5. 第十四章 springboot + profile(不同环境读取不同配置)

    具体做法: 不同环境的配置设置一个配置文件,例如:dev环境下的配置配置在application-dev.properties中:prod环境下的配置配置在application-prod.prope ...

  6. kubernetes实战(二十九):Kubernetes RBAC实现不同用户在不同Namespace的不同权限

    1.基本说明 在生产环境使用k8s以后,大部分应用都实现了高可用,不仅降低了维护成本,也简化了很多应用的部署成本,但是同时也带来了诸多问题.比如开发可能需要查看自己的应用状态.连接信息.日志.执行命令 ...

  7. Redis高可用集群-哨兵模式(Redis-Sentinel)搭建配置教程【Windows环境】

    No cross,no crown . 不经历风雨,怎么见彩虹. Redis哨兵模式,用现在流行的话可以说就是一个"哨兵机器人",给"哨兵机器人"进行相应的配置 ...

  8. apollo配置中心初探

    近在搞微服务框架的开发,需要有一个配置中心来满足统一管理业务应用以及组件的配置,在此期间也使用了多个配置中心比如:spring cloud config,自研的配置中心,当然还有apollo. spr ...

  9. GO学习-(3) VS Code配置Go语言开发环境

    VS Code配置Go语言开发环境 VS Code配置Go语言开发环境 说在前面的话,Go语言是采用UTF8编码的,理论上使用任何文本编辑器都能做Go语言开发.大家可以根据自己的喜好自行选择.编辑器/ ...

随机推荐

  1. 容器编排系统K8s之包管理器helm基础使用(二)

    前文我们介绍了helm的相关术语和使用helm安装和卸载应用,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14305902.html:今天我们来介绍下自定义 ...

  2. C++ STL 优先队列 (priority_queue)

    std::priority_queue <queue> 优先队列   优先队列是一种容器适配器,根据某些严格的弱排序标准,使其第一个元素始终包含的最大元素.   这种特性类似于堆,它可以在 ...

  3. EL&Filter&Listener:EL表达式和JSTL,Servlet规范中的过滤器,Servlet规范中的监听器,观察着设计模式,监听器的使用,综合案例学生管理系统

    EL&Filter&Listener-授课 1 EL表达式和JSTL 1.1 EL表达式 1.1.1 EL表达式介绍 *** EL(Expression Language):表达式语言 ...

  4. linux中的虚拟环境工具

    1.虚拟环境工具的学习 python的虚拟环境,其实就是在机器上,方便的创建出多个解释器,每个解释器运行一个项目,互相之间不受影响 2.virtualenv工具,可以方便的创建,使用,删除也很方便 3 ...

  5. uni-app开发经验分享十八:对接第三方h5

    1.uni-app中对接第三方为了防止跳出app使用了webview <template> <view> <web-view :src="url" @ ...

  6. 为什么从REST转向gRPC 需要流式传输搜索结果,也就是在有第一批结果时就开始传输

    https://mp.weixin.qq.com/s/aEO3Y8SkObNgfQU3z8sH2w 我们为什么从REST转向gRPC 原创 Levin Fritz InfoQ 2019-06-23 作 ...

  7. Certbot CA 证书 https

    certbot (base) a@test:~# certbot --help - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...

  8. linux文件、目录管理

    系统目录结构 ls(list)ls / 根下面的目录每个用户都有一个家目录创建一个普通用户: useradd xfxing可查看该用户:ls /home/xfxing/ (useradd user1 ...

  9. 「笔记」数位DP

    目录 写在前面 引入 求解 特判优化 代码 例题 「ZJOI2010」数字计数 「AHOI2009」同类分布 套路题们 「SDOI2014」数数 写在最后 写在前面 19 年前听 zlq 讲课的时候学 ...

  10. NOIP2020 移球游戏

    Description 给定 \(n+1\) 个栈,前 \(n\) 个栈内有不定的 \(m\) 个元素,最后一个栈为空,每个栈的最大容量为 \(m\) 每种颜色都有 \(m\) 种,求任意一种方法,使 ...