分类目录组件项目

Spring Cloud Stream 分组

服务 介绍
stream-group-sender 消息发送者服务
stream-group-receiverA 消息接收者服务
stream-group-receiverB 消息接收者服务

创建stream-group-sender 服务

spring.application.name=stream-sender
//对应 MQ 是 exchange outputProduct自定义的信息
spring.cloud.stream.bindings.outputProduct.destination=exchangeProduct
1. 定义发送接口

public interface ISendeService {
    String OUTPUT="outputProduct";
    /**
     * 指定输出的交换器名称
     * @return
     */
    @Output(OUTPUT)
    MessageChannel send();
}
  1. 在启动类增加注解
    // 绑定我们刚刚创建的发送消息的接口类型
    @EnableBinding(value={ISendeService.class})
  2. 测试发送
@RunWith(SpringRunner.class)
@SpringBootTest(classes=StreamSenderStart.class)
public class StreamTest {
    @Autowired
    private ISendeService sendService;

    @Test
    public void testStream(){
        Product p = new Product(666, "stream test ...");
        // 将需要发送的消息封装为Message对象
        Message message = MessageBuilder
                                .withPayload(p)
                                .build();
        sendService.send().send(message );
    }
}

创建stream-group-receiverA服务

spring.application.name=stream-group-receiverA
// 对应 MQ 是 exchange 和消息发送者的 交换器是同一个
spring.cloud.stream.bindings.inputProduct.destination=exchangeProduct
// 具体分组 对应 MQ 是 队列名称 并且持久化队列 inputProduct 自定义
spring.cloud.stream.bindings.inputProduct.group=groupProduct
1. 定义接收口

public interface IReceiverService {
    String INPUT = "inputProduct";
    /**
     * 指定接收的交换器名称
     * @return
     */
    @Input(INPUT)
    SubscribableChannel receiver();
}
  1. 消息的具体处理
@Service
@EnableBinding(IReceiverService.class)
public class ReceiverService {
    @StreamListener(IReceiverService.INPUT)
    public void onReceiver(Product p){
        System.out.println("消费者A:"+p);
    }
}
  1. 在启动类添加注解
    @EnableBinding(value={IReceiverService.class})

创建stream-group-receiverB服务

 此服务和stream-group-receiverA一样,复制一份只需修改配制中的服务名称,端口,group设置不一样
在stream-group-receiverA和stream-group-receiverB服务的group不一致的情况下都收到了消息
改为同组的情况下只有其中一个受到消息。避免了消息重复消费

RabbitMq使用

用于异步处理,日志处理,流量削峰,应用解耦

引用依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

参数配制

默认配制
spring:
 rabbitmq:
   host: localhost
   port: 5672
   username: guest
   password: guest

发送消息

public class MqSend {
    @Autowired
    private AmqpTemplate amqpTemplate;

     /**
     * 发送Mq测试消息
     */
    public void send(){
        amqpTemplate.convertAndSend("myQueue","now "+new Date());
    }

    /**
     * 发送数据供应商分组Mq测试消息
     */
    public void sendOrder(){
        amqpTemplate.convertAndSend("myQueue","computer","now "+new Date());
    }

}

接收消息

@Slf4j
@Component
public class MqReceiver {

    //1. 接收手动创建的消息,需先手动创建myQueue队列名
    /*@RabbitListener(queues = "myQueue")
    public void processtest(String message){
        log.info("MQReceiver: {}",message);
    }*/

    //2. 自动创建队列
    // @RabbitListener(queuesToDeclare = @Queue("myQueue"))

    //3. 自动创建, Exchange和Queue绑定
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("myQueue"),
            exchange = @Exchange("myExchange")
    ))
    public void process(String message) {
        log.info("MqReceiver: {}", message);
    }
     /**
     * 数码供应商服务 接收分组消息
     * @param message
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange("myOrder"),
            key = "computer",
            value = @Queue("computerOrder")
    ))
    public void processComputer(String message) {
        log.info("computer MqReceiver: {}", message);
    }

    /**
     * 水果供应商服务 接收分组消息
     * @param message
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange("myOrder"),
            key = "fruit",
            value = @Queue("fruitOrder")
    ))
    public void processFruit(String message) {
        log.info("fruit MqReceiver: {}", message);
    }
}

Feign/RestTemplate

  1. 增加依赖
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. 在启动主类增加注解
@EnableFeignClients
  1. 定义feign调用商品微服务的接口
访问PRODUCT服务下的接口
@FeignClient(name = "PRODUCT")
public interface ProductClient {

    /**
     * 从商品微服务中获取一个测试信息
     * @return
     */
    @GetMapping("/msg")
    String productMsg();

    /**
     * 根据一组商品ID获取商品列表
     * @param productIdList
     * @return
     */
    @PostMapping("/listForOrder")
    List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    /**
     * 扣库存
     * @param decreaseStockInputList
     */
    @PostMapping("/decreaseStock")
    void decreaseStock(@RequestBody List<DecreaseStockInput> decreaseStockInputList);
}

  1. 调用feign接口
@Api(tags="RestTemplate/feign调用微服务API")
@RestController
@Slf4j
public class ClientController {
    /*第二种方式*/
   /* @Autowired
    private LoadBalancerClient loadBalancerClient;*/

    /* 第三种方式
     @Autowired
    private RestTemplate restTemplate;*/

    /*第四种方式feign*/
    @Autowired
    private ProductClient productClient;

    @ApiOperation("获取一个测试信息")
    @GetMapping("/msg")
    public String getProductMsg(){
        //第一种方式 直接使用RestTemplate,URL固定
        //RestTemplate restTemplate = new RestTemplate();
        //String response = restTemplate.getForObject("http://localhost:8080/productserver/msg",String.class);

        //第二种方式 直接使用RestTemplate,URL利用LoadBalancerClient获取
        /*RestTemplate restTemplate = new RestTemplate();
        ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT");
        String url = String.format("http://%s:%s/msg",serviceInstance.getHost(),serviceInstance.getPort());
        String response = restTemplate.getForObject(url,String.class);*/

        //第三种,将 RestTemplate 作为一个Bean 配制到项目,使用注解@LoadBalanced,在restTemplate直接使用应用名字
        //String response = restTemplate.getForObject("http://PRODUCT/msg",String.class);
        //4.feign
        String response = productClient.productMsg();
        log.info("response={}",response);
        return response;
    }
    }
    第三种方式使用注解@LoadBalanced的配制文件
    @Component
    public class RestTemplateConfig {
     @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    or
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        //return new RestTemplate();
        return new RestTemplateBuilder().basicAuthentication("oauth", "123").build();
    }
    }

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add(“grant_type”, “password”);
map.add(“client_id”, “oauth”);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, header);
MyToken myToken = restTemplate.postForObject(“http://192.168.88.108:30002/oauth/token”,request,MyToken.class);

    // build http headers
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization","bearer "+myToken.getAccess_token());
    ResponseEntity<ClientUser[]> responseEntity = restTemplate.exchange(RBAC_SERVER+POST_ALL_USER, HttpMethod.GET,new HttpEntity<String>(headers),ClientUser[].class);

Mongo

mongod docker

4.2.2-bionic, 4.2-bionic, 4-bionic, bionic

docker run -itd --name mongo -p 27017:27017 -v /home/mongo/data:/data/db --restart always mongo --auth
-auth:需要密码才能访问容器服务。

接着使用以下命令添加用户和设置密码,并且尝试连接。

$ docker exec -it mongo mongo admin
创建一个名为 admin,密码为 123456 的用户。
>  db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'}]});
尝试使用上面创建的用户信息进行连接。
> db.auth('admin', '123456')

创建有可读写权限的用户. 对于一个特定的数据库, 比如'demo'
 db.createUser({
     user: 'test',
     pwd: '123456',
     roles: [{role: "read", db: "demo"}]
 })

数据库的建立
use demo;
    mongo 是否正常启动的校验
    先写入一条数据
    db.info.save({name: 'test', age: '22'})
    查看写入的数据
    db.info.find();
    结果如下
    { "_id" : ObjectId("5c973b81de96d4661a1c1831"), "name" : "test", "age" : "22" }
远程连接的开启
在 `mongodb` 的容器当中
#更新源
apt-get update
# 安装 vim
apt-get install vim
# 修改 mongo 配置文件
vim /etc/mongod.conf.orig
将其中的
bindIp: 127.0.0.1
注释掉`# bindIp: 127.0.0.1` 或者改成`bindIp: 0.0.0.0` 即可开启远程连接

k8s web管理 dashboard

确保kubernetes环境正常
官网说明
在GitHub官网中获取dashboard的资源清单:https://github.com/kubernetes/dashboard
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

或手动下载
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
修改配置文件:
vim recommended.yaml
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort ##增加此字段
ports:
– port: 443
targetPort: 8443
nodePort: 30443 #增加
selector:
k8s-app: kubernetes-dashboard

#因为自动生成的证书很多浏览器无法使用,所以我们自己创建,注释掉kubernetes-dashboard-certs对象声明
#apiVersion: v1
#kind: Secret
#metadata:
#  labels:
#    k8s-app: kubernetes-dashboard
#  name: kubernetes-dashboard-certs
#  namespace: kubernetes-dashboard
#type: Opaque
===================================
创建证书
mkdir dashboard-certs
cd dashboard-certs/
#创建命名空间
kubectl create namespace kubernetes-dashboard    #yaml里会自动创建,可以不用单独创建
#创建key文件
openssl genrsa -out dashboard.key 2048
#证书请求
openssl req -days 36000 -new -out dashboard.csr -key dashboard.key -subj '/CN=dashboard-cert'
#自签证书
openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt
#创建kubernetes-dashboard-certs对象
kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kubernetes-dashboard

master上传所需的软件包,可以先下载
kubernetesui/dashboard:v2.0.0-beta8
kubernetesui/metrics-scraper:v1.0.2
安装
kubectl apply -f recommended.yaml
#检查结果
kubectl get pods -A -o wide
kubectl get service -n kubernetes-dashboard -o wide

创建dashboard管理员

cat >> dashboard-admin.yaml<<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: dashboard-admin
  namespace: kubernetes-dashboard
EOF

kubectl create -f dashboard-admin.yaml

为用户分配权限:

cat >>dashboard-admin-bind-cluster-role.yaml<<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dashboard-admin-bind-cluster-role
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: dashboard-admin
  namespace: kubernetes-dashboard
EOF

kubectl create -f dashboard-admin-bind-cluster-role.yaml

访问地址:http://NodeIP:30443

创建service account并绑定默认cluster-admin管理员集群角色:

$ kubectl create serviceaccount dashboard-admin -n kube-system
$ kubectl create clusterrolebinding dashboard-admin –clusterrole=cluster-admin –serviceaccount=kube-system:dashboard-admin
$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk ‘/dashboard-admin/{print $1}’)
使用输出的token登录Dashboard。

Name:         dashboard-admin-token-nlhcc
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: dashboard-admin
              kubernetes.io/service-account.uid: 392bdc7a-4032-4ef1-b5b7-f8d8a816b3b2

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6Im9IXzlYU1d0Ukhsc194aWk5R29TV2h3WGRkaF9LMEVOVWxpRW1IYXBUNUEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tbmxoY2MiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMzkyYmRjN2EtNDAzMi00ZWYxLWI1YjctZjhkOGE4MTZiM2IyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.Jd8vxPSJWvA8vwxgMZ-uSMGPHh7lY2U91Ui5mAZXH25ThSbbbHJotK1A5h6vu4XreGESBiGMKrI1sZViI4ZhaSFt2e25KrwhliYRxEZaJ5hRsBFdxc8sU16UJX9ctHMQ9RbnZyhY8gL7s2Fmz18Keowa5e-bJL7dAyeqH9WtUi_liDZHIKLtf1EtnmOE-NFxGJ7NwZYS6ZsMUXu0e0XkuhkQRE8gVof1QxuJGxtVCw0V8dNCIgzBbbpkSEWXqzHVM5Cceaf888GXqjryvIHJ-UGvKoVc2m_MRpIqLRqjmsHCFGDTFdrWk0XQDT1NcS5jAK6YJ6WW6lhrj5c65puSDQ

.安装metrics-server

在Node上下载镜像文件:

docker pull bluersw/metrics-server-amd64:v0.3.6
docker tag bluersw/metrics-server-amd64:v0.3.6 k8s.gcr.io/metrics-server-amd64:v0.3.6

在Master上执行安装:

git clone https://github.com/kubernetes-incubator/metrics-server.git
cd metrics-server/deploy/1.8+/
修改metrics-server-deployment.yaml
image: k8s.gcr.io/metrics-server-amd64  #在image下添加一下内容
        command:
        - /metrics-server
        - --metric-resolution=30s
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP

查找runAsNonRoot: true  修改为runAsNonRoot: false

kubectl create -f .

如果不能获取不到镜像可以更改image: mirrorgooglecontainers/metrics-server-amd64:v0.3.6

说明:service的三种端口
port:service暴露在集群ip上的端口,提供给集群内部客户访问service入口
odePort:是k8s提供给集群外部客户访问service入口的一种方式
targetPort:targetPort是pod中容器实例上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetport上进入容器

vim /etc/kubernetes/dashboard-deployment.yaml
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
    # Keep the name in sync with image version and
    # gce/coreos/kube-manifests/addons/dashboard counterparts
      name: kubernetes-dashboard-latest
      namespace: kube-system
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            k8s-app: kubernetes-dashboard
            version: latest
            kubernetes.io/cluster-service: "true"
        spec:
          containers:
          - name: kubernetes-dashboard
            image: docker.io/bestwu/kubernetes-dashboard-amd64:v1.6.3
            imagePullPolicy: IfNotPresent
            resources:
              # keep request = limit to keep this container in guaranteed class
              limits:
                cpu: 100m
                memory: 50Mi
              requests:
                cpu: 100m
                memory: 50Mi
            ports:
            - containerPort: 9090
            args:
            - --apiserver-host=http://10.3.20.100:8080
            livenessProbe:
              httpGet:
                path: /
                port: 9090
              initialDelaySeconds: 30
              timeoutSeconds: 30

[root@master-ldy ~]# vim /etc/kubernetes/dashboard-service.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: kubernetes-dashboard
      namespace: kube-system
      labels:
        k8s-app: kubernetes-dashboard
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        k8s-app: kubernetes-dashboard
      ports:
      - port: 80
        targetPort: 9090

FYI1
FYI2

k8s 管理平台 Rancher

rancher
rancher CN

什么版本的Docker才能适配Rancher和Kubernetes
请参考:(http://rancher.com/docs/rancher/v1.6/zh/hosts/#docker)

https://rancher.com/ 新版 V2.X

swapoff -a

docker run  --name rancher --privileged -d --restart=unless-stopped -p 8080:80 -p 8443:443 -v ~/rancher/data:/var/lib/rancher/ rancher/rancher:v2.5.7

docker run -d --name rancher \
-v ~/rancher/data:/var/lib/rancher/ \
--restart=unless-stopped \
--privileged \
-p 8080:80 -p 8443:443 \
-e CATTLE_SYSTEM_CATALOG=bundled \
rancher/rancher:stable \

-v ~/rancher/certs:/container/certs \
-e SSL_CERT_DIR="/container/certs" \
--no-cacerts

-v ~/rancher/certs/sercert.pem:/etc/rancher/ssl/cert.pem \
-v ~/rancher/certs/serprivkey.pem:/etc/rancher/ssl/key.pem \
-v ~/rancher/certs/cacert.pem:/etc/rancher/ssl/cacerts.pem \
--no-cacerts

scp -r D:/Desktop/temp/ ubuntu@119.29.57.229:~/rancher/certs/

证书过期
docker exec c -ti 5b4b6e274b31 mv /var/lib/rancher/management-state/certs/bundle.json /var/lib/rancher/management-state/certs/bundle.json-bak

直接把/var/lib/rancher/k3s/server/tls/下已过期的证书(.crt和.key)删掉,大概有14个,也可以生成新的证书,解决过期问题

重新升级部署前
sudo rm -rf /var/lib/etcd/member/
安装完成后可以通过http://ip:8080 访问Rancher的管理平台

K8S中国区镜像模板配置
打开环境管理页面,点击添加环境模板。命名模板并进入配置页,配置阿里巴巴镜像仓库
私有仓库地址:registry.cn-shenzhen.aliyuncs.com
AAONS组件命名空间:rancher_cn
kubernetes-helm命名空间:rancher_cn
Pod Infra Container Image: rancher_cn/pause-amd64:3.0
保存模板,创建一个Kubernetes环境并添加主机.

部署前或部署时,请使用以下命令将环境的各类信息清理干净:
docker rm -f `docker ps -a -q`
docker system prune -f
docker volume rm $(docker volume ls -q)

for mount in $(mount | grep tmpfs | grep '/var/lib/kubelet' | awk '{ print $3 }') /var/lib/kubelet /var/lib/rancher; do umount $mount; done

sudo rm -rf /etc/ceph \
       /etc/cni/* \
       /opt/cni/* \
       /opt/rke \
      /etc/kubernetes \
       /run/secrets/kubernetes.io \
       /run/calico/* \
       /run/flannel/* \
       /var/lib/calico/* \
       /var/lib/cni/* \
       /var/lib/kubelet/* \
       /var/lib/rancher/rke/log \
       /var/log/containers/* \
       /var/log/pods/* \
       /var/run/calico/* \
       /var/lib/rancher/* \
       /var/lib/docker/* \
       /var/lib/etcd/* \
      /var/lib/kubelet/* \
  ~/rancher/*

ip link del flannel.1
ip link del cni0

sudo rm -f /var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db
sudo systemctl restart containerd
sudo systemctl restart docker

iptables -F && iptables -t nat -F

.rke remove
重启

k8s集群管理平台 wayne

### wayne
https://github.com/Qihoo360/wayne.git
架构

说明文档

开发版项目依赖
Golang 1.12+(installation manual)
Docker 17.05+ (installation manual)
Bee (installation manual) (请务必使用链接版本,不要使用 beego 官方版本,存在一些定制)
Node.js 8+ and npm 5+ (installation with nvm)
MySQL 5.6+ (Wayne 主要数据都存在 MySQL 中)
RabbitMQ (可选,如需扩展审计功能,例如操作审计和 Webhooks 等,则需部署)

快速启动
克隆代码仓库
$ go get github.com/Qihoo360/wayne
启动服务
在 Wayne 的根目录下,通过 docker-compose 创建服务
$ docker-compose -f ./hack/docker-compose/docker-compose.yaml up
通过上述命令,您可以从通过 http://127.0.0.1:4200 访问本地 Wayne, 默认管理员账号 admin:admin。
注意:项目启动后还需要配置集群和Namespace等信息才可正常使用。详见 集群配置

由于前后端使用 JWT Token 通信,生产环境一定要重新生成 RSA 文件,确保安全。生成 RSA 加密对命令如下:
$ ssh-keygen -t rsa -b 2048 -f jwtRS256.key
$ # Don’t add passphrase
$ openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub

harbor 镜像仓库

代码仓库
项目网站
离线包下载

安装

  1. 安装 docker
  2. 安装 docker-compose
  3. 下载 harbor
    wget https://github.com/goharbor/harbor/releases/download/v1.10.0/harbor-offline-installer-v1.10.0.tgz
  4. 解压
  5. 创建数据目录
    /data/harbor
  6. 创建CA证书
    /data/harbor/cert

    • 创建CA的证书
      openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
    • 生成CA证书签名请求
      openssl req -newkey rsa:4096 -nodes -sha256 -keyout harbor.xxx.com.key -out harbor.xxx.com.csr
    • 生成注册主机的证书
    1. 使用域名生成注册主机证书
      openssl x509 -req -days 365 -in harbor.xxx.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out harbor.xxx.com.crt
    2. 使用IP生成注册主机证书
      echo subjectAltName = IP:192.168.88.88 > extfile.cnf
      openssl x509 -req -days 365 -in harbor.xxx.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out harbor.xxx.com.crt
  7. 配制 配置文件 harbor.cfg or harbor.yml

#配置访问的地址
hostname = 198.168.88.88
#使用http方式访问管理界面
ui_url_protocol = http
#配置admin的密码,默认是Harbor12345
harbor_admin_password = 12345
#更改harbor存储路径,默认是/data
secretkey_path = /data/harbor
certificate: /data/harbor/cert/harbor.xxx.com.crt
private_key: /data/harbor/cert/harbor.xxx.com.key
  1. 配置文件docker-compose.yml
  /compose_location/docker-compose.yml
  1. 检测并创建harbor需要文件
    ./prepare
  2. 安装Harbor
    ./install.sh

  3. 保存数据重新安装 (先进入harbor目录)
    docker-compose up -d
    docker-compose down -v
    ./install.sh可以重新安装

默认安装管理Harbor的生命周期

ocker-compose ps 查看
开始、停止、重启
您可以使用docker-compose来管理Harbor的生命周期。一些有用的命令列出如下(必须与docker-compose.yml在同一目录中运行)。
sudo docker-compose start/stop/restart
更新配置
要更改Harbour的配置,请先停止现有的Harbor实例并进行更新harbor.cfg。然后运行prepare脚本以填充配置。最后重新创建并启动Harbor的实例:
sudo docker-compose down -v
sudo vim harbor.cfg
sudo prepare
sudo docker-compose up -d
删除Harbor的容器,同时将镜像数据和Harbor的数据库文件保存在文件系统上
sudo docker-compose down -v
删除Harbor的数据库和镜像数据(用于干净的重新安装)
rm -r /data/database
rm -r /data/registry

  1. 管理界面
    注:默认的用户名admin,密码Harbor12345。

  2. 错误

    • Error response from daemon: Get https://harbor.xxx.com/v1/users/: x509: certificate signed by unknown authority
      centos7系统以上报错的原因是因为自签的证书没有加入到系统级别信任,只需要将harbor.xxx.com.crt拷贝到/etc/pki/ca-trust/source/anchors/reg.你的域名.crt,然后需要执行命令update-ca-trust,最后重启harbor和docker即可!
      ubunt16.04系统以上报错的原因是因为自签的证书没有加入到系统级别信任,只需要将harbor.xxx.com.crt拷贝到/usr/local/share/ca-certificates/reg.你的域名.crt,然后执行命令update-ca-certificates,最后重启harbor和docker即可!
      /usr/share/ca-certificates/reg.你的域名.crt
      图形化配制 dpkg-reconfigure ca-certificates
      client:
      确认证书是 crt 结尾的,不是按照如下命令转换
      $ openssl x509 -inform PEM -in root-ca.cer -out root-ca.crt
      拷贝证书文件到 /usr/local/share/ca-certificates
      $ sudo cp root-ca.crt /usr/local/share/ca-certificates/
      修改ca 配置文件
      编辑 /etc/ca-certificates.conf。文件最后加入 ‘root-ca.crt’。里面文件的位置是相对 /usr/local/share/ca-certificates/
      更新本机的ca 文件
      $ sudo update-ca-certificates
      Mac OS X
      添加证书:
      sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/new-root-certificate.crt
      移除证书:
      sudo security delete-certificate -c “”
  • Error response from daemon: Get https://192.168.88.88/v2/: dial tcp 192.168.88.88:443: connect: connection refused
    在docker启动文件中添加–insecure-registry信任关系!
    cat /usr/lib/systemd/system/docker.service -> –insecure-registry=harbor仓库IP地址+端口号
    修改docker客户端配置/etc/default/docker
    备注:增加harbor私有仓库地址,告知客户端要连接http的端口
    DOCKER_OPTS=”–selinux-enabled –log-driver=journald –signature-verification=false –insecure-registry=192.168.88.98″
    Server DOCKER_OPTS=”–insecure-registry 192.168.88.98″
    vi /etc/systemd/system/multi-user.target.wants/docker.service
    ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS
  • denied: requested access to the resource is denied
    vi /etc/docker/daemon.json
    {
    "insecure-registries":["192.168.88.98:5000"],
    "registry-mirrors":["https://cuzn52f3.mirror.aliyuncs.com","https://registry.docker-cn.com","https://reg-mirror.qiniu.com"],
    "exec-opts": ["native.cgroupdriver=systemd"]
    }
    vi /etc/default/docker
    DOCKER_OPTS="--insecure-registry 192.168.88.98"
    vi /etc/systemd/system/multi-user.target.wants/docker.service
    可以在systemctl status docker 中查看具体配制文件路径
    ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS

    删除证书
    $sudo rm -f /usr/local/share/ca-certificates/xinmu.crt
    $sudo update-ca-certificates
    或编辑 /etc/ca-certificates.conf 文件,把证书对应的行删除或注释掉。然后用命令 update-ca-certificates 使之生效。

    1. FYI
      (https://blog.51cto.com/13043516/2287267)
      (http://blog.itpub.net/28624388/viewspace-2153546/)

Docker Compose

Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具

安装 Docker Compose

官网
1. 安装 Docker Compose 可以通过下面命令自动下载适应版本的 Compose,并为安装脚本添加执行权限

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

使用工具安装 pip install docker-compose

  1. 查看安装是否成功
    docker-compose -v

快速入门

  1. 打包项目,获得 jar 包 docker-demo-0.0.1-SNAPSHOT.jar
    mvn clean package
  2. 在 jar 包所在路径创建 Dockerfile 文件,添加以下内容
    FROM java:8
    VOLUME /tmp
    ADD docker-demo-0.0.1-SNAPSHOT.jar app.jar
    RUN bash -c ‘touch /app.jar’
    EXPOSE 9000
    ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-jar”,”app.jar”]
  3. 在 jar 包所在路径创建文件 docker-compose.yml,添加以下内容
version: '2' # 表示该 Docker-Compose 文件使用的是 Version 2 file
services:
  docker-demo:  # 指定服务名称
    build: .  # 指定 Dockerfile 所在路径
    ports:    # 指定端口映射
      - "9000:8761"

在 docker-compose.yml 所在路径下执行该命令 Compose 就会自动构建镜像并使用镜像启动容器
docker-compose up
docker-compose up -d // 后台启动并运行容器
访问 http://localhost:9000/hello 即可访问微服务接口

工程、服务、容器

Docker Compose 将所管理的容器分为三层,分别是工程(project)、服务(service)、容器(container)
Docker Compose 运行目录下的所有文件(docker-compose.yml)组成一个工程,一个工程包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖,一个服务可包括多个容器实例
Docker Compose 常用命令与配置

常见命令

ps:列出所有运行容器
docker-compose ps
logs:查看服务日志输出
docker-compose logs
port:打印绑定的公共端口,下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口
docker-compose port eureka 8761
build:构建或者重新构建服务
docker-compose build
start:启动指定服务已存在的容器
docker-compose start eureka
stop:停止已运行的服务的容器
docker-compose stop eureka
rm:删除指定服务的容器
docker-compose rm eureka
up:构建、启动容器
docker-compose up
kill:通过发送 SIGKILL 信号来停止指定服务的容器
docker-compose kill eureka
pull:下载服务镜像
scale:设置指定服务运气容器的个数,以 service=num 形式指定
docker-compose scale user=3 movie=3
run:在一个服务上执行一个命令
docker-compose run web bash
docker-compose.yml 属性

version:指定 docker-compose.yml 文件的写法格式
services:多个容器集合
build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 参数

““

build: ./dir

build:
context: ./dir
dockerfile: Dockerfile
args:
buildno: 1
command:覆盖容器启动后默认执行的命令

command: bundle exec thin -p 3000

command: [bundle,exec,thin,-p,3000]
dns:配置 dns 服务器,可以是一个值或列表

dns: 8.8.8.8

dns:
– 8.8.8.8
– 9.9.9.9
dns_search:配置 DNS 搜索域,可以是一个值或列表

dns_search: example.com

dns_search:
– dc1.example.com
– dc2.example.com
environment:环境变量配置,可以用数组或字典两种方式
environment:
RACK_ENV: development

SHOW: ‘ture’

environment:
– RACK_ENV=development
– SHOW=ture
env_file:从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量

env_file: .env

env_file:
– ./common.env
expose:暴露端口,只将端口暴露给连接的服务,而不暴露给主机
expose:
– “3000”
– “8000”
image:指定服务所使用的镜像
image: java
network_mode:设置网络模式
network_mode: “bridge”
network_mode: “host”
network_mode: “none”
network_mode: “service:[service name]”
network_mode: “container:[container name/id]”
ports:对外暴露的端口定义,和 expose 对应
ports: # 暴露端口信息 – “宿主机端口:容器暴露端口”
– “8763:8763”
– “8763:8763”
links:将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
links: # 指定服务名称:别名
– docker-compose-eureka-server:compose-eureka
volumes:卷挂载路径
volumes:
– /lib
– /var
logs:日志输出信息
–no-color 单色输出,不显示其他颜.
-f, –follow 跟踪日志输出,就是可以实时查看日志
-t, –timestamps 显示时间戳
–tail 从日志的结尾显示,–tail=200
Docker Compose 其它

更新容器

当服务的配置发生更改时,可使用 docker-compose up 命令更新配置
此时,Compose 会删除旧容器并创建新容器,新容器会以不同的 IP 地址加入网络,名称保持不变,任何指向旧容起的连接都会被关闭,重新找到新容器并连接上去
links

服务之间可以使用服务名称相互访问,links 允许定义一个别名,从而使用该别名访问其它服务

version: ‘2’
services:
web:
build: .
links:
– “db:database”
db:
image: postgres
这样 Web 服务就可以使用 db 或 database 作为 hostname 访问 db 服务了

jar 工程 docker 方式部署

.编写超级简单版本的 dockerfile 文件:

# jdk 是一个已有的包含 jdk 的镜像 mcr.microsoft.com/java/jdk:8u232-zulu-ubuntu
FROM jdk
# 作者签名
MAINTAINER JY
# 简化 jar 的名字路径 (#:表示注释掉)
COPY jar/eurekaserver-0.0.1-SNAPSHOT.jar /app.jar

ADD  eurekaserver-0.0.1-SNAPSHOT.jar  /app.jar             #复制本地jar到镜像中

# 执行 java -jar 命令 (CMD:在启动容器时才执行此行。RUN:构建镜像时就执行此行)
CMD java -jar /app.jar

#CMD [“bash”,“-c”,“java -jar app.jar”]

ENTRYPOINT  [“java”,“-jar”,“app.jar”]     #执行的命令

# 设置对外端口
EXPOSE 8761

通过 dockerfile 文件生成本工程的镜像:
docker build -t gentle .

======================================

参考自动脚本构建

cd gentle_code
# 备份原代码
tar -zcvf gentle.tar ./gentle
# 删除原代码文件夹
rm -rf gentle
# 拉取代码
echo -e “\033[32m\n从git拉取代码\n\033[0m”
git clone https://gitee.com/FJ_WoMenDeShiJie/gentle.git
echo -e “\033[32m\n代码拉取完成\n\033[0m”
# 工程打包
cd gentle
rm -rf ./target/gentle-1.0-SNAPSHOT.jar
echo -e “\033[32m\n开始打jar包\n\033[0m”
mvn install -Dmaven.test.skip=true
rm -rf ../../jar/gentle-1.0-SNAPSHOT.jar
cp ./target/gentle-1.0-SNAPSHOT.jar ../../jar
echo -e “\033[32m\njar包完成\n\033[0m”
# 删除原镜像
docker rmi gentle &> /dev/null
echo -e “\033[32m\n删除原镜像\n\033[0m”
echo -e “\033[32m\n构建新镜像\n\033[0m”
cd ../../
docker build -t gentle .
echo -e “\033[32m\n新镜像构建成功\n\033[0m”
# 删除原容器
docker rm -f gentle
# 启动容器
docker run -d -p 8089:8089 –name gentle gentle
echo -e “\033[32m\n后端工程部署完成\n\033[0m”
======================================

或者使用手动更新jar包时,需要在把xxx.jar包复制进容器时,统一重命名为app.jar
docker cp 宿主机jar包 容器名(或容器ID):/app.jar

说明:此方式的优势在于:每次如果要更新jar包,只需要先将容器stop,然后直接替换容器里面的jar包,最后再将该容
器start即可。无需每次都创建新的镜像,创建新的容器。