zoukankan      html  css  js  c++  java
  • CKA-docker 容器的管理

     

    容器的生命期的问题

    -i 交互

    -t 终端

    -d 守护进程(后台运行)

    -e 指定变量

    --rm  临时容器            --restart=always 不能同时使用

    --name 指定容器名

    # 进入容器

    docker attach <容器ID>

     

    docker run -dit --name=c1 --restart=always  hub.c.163.com/library/centos

    # 查看容器信息

    docker inspect c1

    docker top <容器名> 

    # 读取容器里面的输出 

    docker logs <容器名>

    # 在容器mysql镜像,指定了一个变量

     # 额外的打开一个bash进程

     # 冒号左边是物理机,冒号右边是容器

    • docker exec <容器名> 命令
    • docker start <容器名>
    • docker stop <容器名>
    • docker restrart <容器名>
    • docker top <容器名>
    • docker logs -f <容器名>
    • docker inspect <容器名> 
    • docker cp <拷贝的文件> <容器名>:<目录>           docker cp <容器名>:<目录> <物理机存放地址>  # 容器之间不能这样拷贝

     

      weavescope  工具安装测试

    容器监控工具WeaveScope

    github开源项目地址

    curl -L git.io/scope -o /usr/local/bin/scope

    赋予可执行权限:

    chmod a+x /usr/local/bin/scope

    启动scope:

    scope launch

     

      

    数据卷的使用

    -v /dir                  # 默认指定一个目录,是容器里面的目录。物理机是随机生成一个目录

    -v /dir2:dir           # 冒号左边是物理机里面的目录,冒号右边的是容器目录

    -v /dir2:/dir:rw    # 默认

    -v /dir2:/dir:ro  # 需要手动指定只读

    你得去理解容器里的存储信息(比如:mysql本身存放在哪里的)

    # 需要自己再熟悉下 apache tomcat redis

     

     

    docker网络管理

    # 查看容器ip地址

      

     # 查看本地网桥

    docker network list

    # 查看网络属性

    docker network inspect bridge

    # 会生成docker0

      

    # 自己创建一个网桥

    docker network create -d bridge --subnet=x.x.x.x/24 <网桥名>

     PS: 如何自己通过命令查询 创建网络命令

    容器网络里面有

    bridge  网桥 相当于nat

    host   直接变成主机网络

    none 不设置网络(单独配合一些工具可以变成桥接模式,设置独立IP地址) 

    # 加入到自己的创建的网桥

    # 查看应用所需要的变量,例如wordpress

    PS:可以使用hub或者163里面的 how to use 来看下所需的变量意思

    网易:https://c.163yun.com/hub#/home

    # 查找docker 所有相关帮助命令

    man -k docker

    # 新建一个数据库,使用了两个变量(一个是设置root密码,一个是创建数据库)

      

    # 创建wordpress (正常方式)

      

    # 查看更详细的信息

    docker history  --no-trunc  

     # 再次新建后使用 --link 别名 来省略一些变量参数,并且防止容器内部IP变化导致的配置文件修改  【这部分需要进行试验一下】

     

      

    自定义镜像

    构建镜像:并非是从0到1的过程,在一个已经存在的镜像的基础上,进行构建出新的镜像

    基镜像,基础镜像

    最底层的---是一个干净的操作系统,一般是由厂商来提供

    Dockefile

    #############

    RUN

    ADD

    ENV 

    VOLUME

    CMD

    #############

    # 通过dockerfile 生成容器

    1. 生成临时容器,执行dockerfile 内容,产生容器,最后删除临时容器

     Dockefile 文件举例:

    tar tf  <tar> 查看tar包里面内容

    docker build -t centos:v0 .

    . 当前目录去找(其他目录就用-f [dockerfile文件名],不跟文件名,默认寻找Dockerfile)

    ADD 和 COPY 区别 (需实验)

     add 可以解压,copy 直接复制包(不带解压功能) 
    PS: 目前已知能直接解压的有tar,tar.gz 

    自己搭建一个nginx 镜像

    # 可以自己修改nginx配置文件

     # 守护进程模式开启的方法, docker history  --no-trunc  | tail -2 

     EXPOSE 仅仅是个标识 <--- 告诉别人你默认用的端口是什么

    # 如何判断 CMD 后面需要填写的守护进程参数(需要根据经验,或者找一个镜像通过docker histroy查看)

    Nginx:

    CMD ["nginx", "-g", "daemon off;"]

    SSH:

    CMD["sshd", "-D"]

    Mysql:

    CMD ["mysqld"]

    Centos:

    CMD ["/bin/bash"]

    # ENV 和 用户添加

    ENV

    USER

    # Dockerfile RUN 尽量放在一行来写,会减少镜像层数,从而减小镜像的大小

    # 在dockerfile 里面指定用户执行进程,并设置变量 aa

    # 如果创建的进程是普通用户,想用root进入  docker exec -it -uroot .....的方式

    # VOLUME 定义卷

    VOLUME ["dir1", "dir2"]

    # ssh 的dockerfile 是如何一步步做出这个文件的

      

    私有仓库 

    # 搭建自己的私有仓库

    1. registry

    2. harbor

     使用registry 搭建私有仓库

    registry  端口5000

    /var/lib/registry

    1. 仅允许https 方式访问 

    http+ssl -- tls(传输层的加密)

    两种只能选一种,不要都使用

    # 方法一:

    修改 不适用https 的方式,都需要修改

    /etc/docker/daemon.json

     # 方法二:

     

      

     

     # 从客户端推送镜像到私有仓库

    # 修改tag

     # 再进行推送(推送的时候一定要注意镜像tag是不是复核规范

     #使用curl命令查询的镜像数量

    # 查询镜像的版本

     

    使用脚本来实现查询镜像和版本

    # 老师的脚本,仅供参考

     1 #!/bin/bash
     2 file=$(mktemp)
     3 curl -s $1:5000/v2/_catalog | jq | egrep -v '{|}|[|]' | awk -F" '{print $2}' > $file
     4 while read aa ; do
     5 tag=($(curl -s $1:5000/v2/$aa/tags/list | jq | egrep -v '{|}|[|]|name' | awk -F" '{print $2}'))
     6     for i in ${tag[*]} ; do
     7       echo $1:5000/${aa}:$i
     8     done
     9 done < $file
    10 rm -rf $file
    View Code

    # 用脚本查询结果

    # 删除私有仓库下面多余或无用的镜像

    用老师的PY脚本

    #!/usr/bin/env python
    """
    Usage:
    Shut down your registry service to avoid race conditions and possible data loss
    and then run the command with an image repo like this:
    delete_docker_registry_image.py --image awesomeimage --dry-run
    """
    
    import argparse
    import json
    import logging
    import os
    import sys
    import shutil
    import glob
    
    logger = logging.getLogger(__name__)
    
    
    def del_empty_dirs(s_dir, top_level):
        """recursively delete empty directories"""
        b_empty = True
    
        for s_target in os.listdir(s_dir):
            s_path = os.path.join(s_dir, s_target)
            if os.path.isdir(s_path):
                if not del_empty_dirs(s_path, False):
                    b_empty = False
            else:
                b_empty = False
    
        if b_empty:
            logger.debug("Deleting empty directory '%s'", s_dir)
            if not top_level:
                os.rmdir(s_dir)
    
        return b_empty
    
    
    def get_layers_from_blob(path):
        """parse json blob and get set of layer digests"""
        try:
            with open(path, "r") as blob:
                data_raw = blob.read()
                data = json.loads(data_raw)
                if data["schemaVersion"] == 1:
                    result = set([entry["blobSum"].split(":")[1] for entry in data["fsLayers"]])
                else:
                    result = set([entry["digest"].split(":")[1] for entry in data["layers"]])
                    if "config" in data:
                        result.add(data["config"]["digest"].split(":")[1])
                return result
        except Exception as error:
            logger.critical("Failed to read layers from blob:%s", error)
            return set()
    
    
    def get_digest_from_blob(path):
        """parse file and get digest"""
        try:
            with open(path, "r") as blob:
                return blob.read().split(":")[1]
        except Exception as error:
            logger.critical("Failed to read digest from blob:%s", error)
            return ""
    
    
    def get_links(path, _filter=None):
        """recursively walk `path` and parse every link inside"""
        result = []
        for root, _, files in os.walk(path):
            for each in files:
                if each == "link":
                    filepath = os.path.join(root, each)
                    if not _filter or _filter in filepath:
                        result.append(get_digest_from_blob(filepath))
        return result
    
    
    class RegistryCleanerError(Exception):
        pass
    
    
    class RegistryCleaner(object):
        """Clean registry"""
    
        def __init__(self, registry_data_dir, dry_run=False):
            self.registry_data_dir = registry_data_dir
            if not os.path.isdir(self.registry_data_dir):
                raise RegistryCleanerError("No repositories directory found inside " 
                                           "REGISTRY_DATA_DIR '{0}'.".
                                           format(self.registry_data_dir))
            self.dry_run = dry_run
    
        def _delete_layer(self, repo, digest):
            """remove blob directory from filesystem"""
            path = os.path.join(self.registry_data_dir, "repositories", repo, "_layers/sha256", digest)
            self._delete_dir(path)
    
        def _delete_blob(self, digest):
            """remove blob directory from filesystem"""
            path = os.path.join(self.registry_data_dir, "blobs/sha256", digest[0:2], digest)
            self._delete_dir(path)
    
        def _blob_path_for_revision(self, digest):
            """where we can find the blob that contains the json describing this digest"""
            return os.path.join(self.registry_data_dir, "blobs/sha256",
                                digest[0:2], digest, "data")
    
        def _blob_path_for_revision_is_missing(self, digest):
            """for each revision, there should be a blob describing it"""
            return not os.path.isfile(self._blob_path_for_revision(digest))
    
        def _get_layers_from_blob(self, digest):
            """get layers from blob by digest"""
            return get_layers_from_blob(self._blob_path_for_revision(digest))
    
        def _delete_dir(self, path):
            """remove directory from filesystem"""
            if self.dry_run:
                logger.info("DRY_RUN: would have deleted %s", path)
            else:
                logger.info("Deleting %s", path)
                try:
                    shutil.rmtree(path)
                except Exception as error:
                    logger.critical("Failed to delete directory:%s", error)
    
        def _delete_from_tag_index_for_revision(self, repo, digest):
            """delete revision from tag indexes"""
            paths = glob.glob(
                os.path.join(self.registry_data_dir, "repositories", repo,
                             "_manifests/tags/*/index/sha256", digest)
            )
            for path in paths:
                self._delete_dir(path)
    
        def _delete_revisions(self, repo, revisions, blobs_to_keep=None):
            """delete revisions from list of directories"""
            if blobs_to_keep is None:
                blobs_to_keep = []
            for revision_dir in revisions:
                digests = get_links(revision_dir)
                for digest in digests:
                    self._delete_from_tag_index_for_revision(repo, digest)
                    if digest not in blobs_to_keep:
                        self._delete_blob(digest)
    
                self._delete_dir(revision_dir)
    
        def _get_tags(self, repo):
            """get all tags for given repository"""
            path = os.path.join(self.registry_data_dir, "repositories", repo, "_manifests/tags")
            if not os.path.isdir(path):
                logger.critical("No repository '%s' found in repositories directory %s",
                                 repo, self.registry_data_dir)
                return None
            result = []
            for each in os.listdir(path):
                filepath = os.path.join(path, each)
                if os.path.isdir(filepath):
                    result.append(each)
            return result
    
        def _get_repositories(self):
            """get all repository repos"""
            result = []
            root = os.path.join(self.registry_data_dir, "repositories")
            for each in os.listdir(root):
                filepath = os.path.join(root, each)
                if os.path.isdir(filepath):
                    inside = os.listdir(filepath)
                    if "_layers" in inside:
                        result.append(each)
                    else:
                        for inner in inside:
                            result.append(os.path.join(each, inner))
            return result
    
        def _get_all_links(self, except_repo=""):
            """get links for every repository"""
            result = []
            repositories = self._get_repositories()
            for repo in [r for r in repositories if r != except_repo]:
                path = os.path.join(self.registry_data_dir, "repositories", repo)
                for link in get_links(path):
                    result.append(link)
            return result
    
        def prune(self):
            """delete all empty directories in registry_data_dir"""
            del_empty_dirs(self.registry_data_dir, True)
    
        def _layer_in_same_repo(self, repo, tag, layer):
            """check if layer is found in other tags of same repository"""
            for other_tag in [t for t in self._get_tags(repo) if t != tag]:
                path = os.path.join(self.registry_data_dir, "repositories", repo,
                                    "_manifests/tags", other_tag, "current/link")
                manifest = get_digest_from_blob(path)
                try:
                    layers = self._get_layers_from_blob(manifest)
                    if layer in layers:
                        return True
                except IOError:
                    if self._blob_path_for_revision_is_missing(manifest):
                        logger.warn("Blob for digest %s does not exist. Deleting tag manifest: %s", manifest, other_tag)
                        tag_dir = os.path.join(self.registry_data_dir, "repositories", repo,
                                               "_manifests/tags", other_tag)
                        self._delete_dir(tag_dir)
                    else:
                        raise
            return False
    
        def _manifest_in_same_repo(self, repo, tag, manifest):
            """check if manifest is found in other tags of same repository"""
            for other_tag in [t for t in self._get_tags(repo) if t != tag]:
                path = os.path.join(self.registry_data_dir, "repositories", repo,
                                    "_manifests/tags", other_tag, "current/link")
                other_manifest = get_digest_from_blob(path)
                if other_manifest == manifest:
                    return True
    
            return False
    
        def delete_entire_repository(self, repo):
            """delete all blobs for given repository repo"""
            logger.debug("Deleting entire repository '%s'", repo)
            repo_dir = os.path.join(self.registry_data_dir, "repositories", repo)
            if not os.path.isdir(repo_dir):
                raise RegistryCleanerError("No repository '{0}' found in repositories "
                                           "directory {1}/repositories".
                                           format(repo, self.registry_data_dir))
            links = set(get_links(repo_dir))
            all_links_but_current = set(self._get_all_links(except_repo=repo))
            for layer in links:
                if layer in all_links_but_current:
                    logger.debug("Blob found in another repository. Not deleting: %s", layer)
                else:
                    self._delete_blob(layer)
            self._delete_dir(repo_dir)
    
        def delete_repository_tag(self, repo, tag):
            """delete all blobs only for given tag of repository"""
            logger.debug("Deleting repository '%s' with tag '%s'", repo, tag)
            tag_dir = os.path.join(self.registry_data_dir, "repositories", repo, "_manifests/tags", tag)
            if not os.path.isdir(tag_dir):
                raise RegistryCleanerError("No repository '{0}' tag '{1}' found in repositories "
                                           "directory {2}/repositories".
                                           format(repo, tag, self.registry_data_dir))
            manifests_for_tag = set(get_links(tag_dir))
            revisions_to_delete = []
            blobs_to_keep = []
            layers = []
            all_links_not_in_current_repo = set(self._get_all_links(except_repo=repo))
            for manifest in manifests_for_tag:
                logger.debug("Looking up filesystem layers for manifest digest %s", manifest)
    
                if self._manifest_in_same_repo(repo, tag, manifest):
                    logger.debug("Not deleting since we found another tag using manifest: %s", manifest)
                    continue
                else:
                    revisions_to_delete.append(
                        os.path.join(self.registry_data_dir, "repositories", repo,
                                     "_manifests/revisions/sha256", manifest)
                    )
                    if manifest in all_links_not_in_current_repo:
                        logger.debug("Not deleting the blob data since we found another repo using manifest: %s", manifest)
                        blobs_to_keep.append(manifest)
    
                    layers.extend(self._get_layers_from_blob(manifest))
    
            layers_uniq = set(layers)
            for layer in layers_uniq:
                if self._layer_in_same_repo(repo, tag, layer):
                    logger.debug("Not deleting since we found another tag using digest: %s", layer)
                    continue
    
                self._delete_layer(repo, layer)
                if layer in all_links_not_in_current_repo:
                    logger.debug("Blob found in another repository. Not deleting: %s", layer)
                else:
                    self._delete_blob(layer)
    
            self._delete_revisions(repo, revisions_to_delete, blobs_to_keep)
            self._delete_dir(tag_dir)
    
        def delete_untagged(self, repo):
            """delete all untagged data from repo"""
            logger.debug("Deleting utagged data from repository '%s'", repo)
            repositories_dir = os.path.join(self.registry_data_dir, "repositories")
            repo_dir = os.path.join(repositories_dir, repo)
            if not os.path.isdir(repo_dir):
                raise RegistryCleanerError("No repository '{0}' found in repositories "
                                           "directory {1}/repositories".
                                           format(repo, self.registry_data_dir))
            tagged_links = set(get_links(repositories_dir, _filter="current"))
            layers_to_protect = []
            for link in tagged_links:
                layers_to_protect.extend(self._get_layers_from_blob(link))
    
            unique_layers_to_protect = set(layers_to_protect)
            for layer in unique_layers_to_protect:
                logger.debug("layer_to_protect: %s", layer)
    
            tagged_revisions = set(get_links(repo_dir, _filter="current"))
    
            revisions_to_delete = []
            layers_to_delete = []
    
            dir_for_revisions = os.path.join(repo_dir, "_manifests/revisions/sha256")
            for rev in os.listdir(dir_for_revisions):
                if rev not in tagged_revisions:
                    revisions_to_delete.append(os.path.join(dir_for_revisions, rev))
                    for layer in self._get_layers_from_blob(rev):
                        if layer not in unique_layers_to_protect:
                            layers_to_delete.append(layer)
    
            unique_layers_to_delete = set(layers_to_delete)
    
            self._delete_revisions(repo, revisions_to_delete)
            for layer in unique_layers_to_delete:
                self._delete_blob(layer)
                self._delete_layer(repo, layer)
    
    
        def get_tag_count(self, repo):
            logger.debug("Get tag count of repository '%s'", repo)
            repo_dir = os.path.join(self.registry_data_dir, "repositories", repo)
            tags_dir = os.path.join(repo_dir, "_manifests/tags")
    
            if os.path.isdir(tags_dir):
                tags = os.listdir(tags_dir)
                return len(tags)
            else:
                logger.info("Tags directory does not exist: '%s'", tags_dir)
                return -1
    
    def main():
        """cli entrypoint"""
        parser = argparse.ArgumentParser(description="Cleanup docker registry")
        parser.add_argument("-i", "--image",
                            dest="image",
                            required=True,
                            help="Docker image to cleanup")
        parser.add_argument("-v", "--verbose",
                            dest="verbose",
                            action="store_true",
                            help="verbose")
        parser.add_argument("-n", "--dry-run",
                            dest="dry_run",
                            action="store_true",
                            help="Dry run")
        parser.add_argument("-f", "--force",
                            dest="force",
                            action="store_true",
                            help="Force delete (deprecated)")
        parser.add_argument("-p", "--prune",
                            dest="prune",
                            action="store_true",
                            help="Prune")
        parser.add_argument("-u", "--untagged",
                            dest="untagged",
                            action="store_true",
                            help="Delete all untagged blobs for image")
        args = parser.parse_args()
    
    
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter(u'%(levelname)-8s [%(asctime)s]  %(message)s'))
        logger.addHandler(handler)
    
        if args.verbose:
            logger.setLevel(logging.DEBUG)
        else:
            logger.setLevel(logging.INFO)
    
    
        # make sure not to log before logging is setup. that'll hose your logging config.
        if args.force:
            logger.info(
                "You supplied the force switch, which is deprecated. It has no effect now, and the script defaults to doing what used to be only happen when force was true")
    
        splitted = args.image.split(":")
        if len(splitted) == 2:
            image = splitted[0]
            tag = splitted[1]
        else:
            image = args.image
            tag = None
    
        if 'REGISTRY_DATA_DIR' in os.environ:
            registry_data_dir = os.environ['REGISTRY_DATA_DIR']
        else:
            registry_data_dir = "/opt/registry_data/docker/registry/v2"
    
        try:
            cleaner = RegistryCleaner(registry_data_dir, dry_run=args.dry_run)
            if args.untagged:
                cleaner.delete_untagged(image)
            else:
                if tag:
                    tag_count = cleaner.get_tag_count(image)
                    if tag_count == 1:
                        cleaner.delete_entire_repository(image)
                    else:
                        cleaner.delete_repository_tag(image, tag)
                else:
                    cleaner.delete_entire_repository(image)
    
            if args.prune:
                cleaner.prune()
        except RegistryCleanerError as error:
            logger.fatal(error)
            sys.exit(1)
    
    
    if __name__ == "__main__":
        main()
    View Code

    # 首先,用export定义变量 REGISTRY_DATA_DIR 也就是Registry设置的映射盘路径

    # 然后,执行脚本 -i 跟上镜像完整名字

      

     

    使用harbor 搭建私有仓库

     PS: 注意安装的时候上面不能同时存在Registry!!!

    # 记得先修改不使用https

       

      

     # 安装docker 编排工具

    yum install docker-compose 

    # haror 离线包

    https://github.com/goharbor/harbor/releases

    解压,导入镜像.tar 

    拷贝模板

    cp harbor.yml.tmpl harbor.yml

    修改配置文件

    注释掉https(生产环境视情况)

    默认是80端口(生产环境注意修改)

    查看Harbor初始密码(生产环境注意修改)

    admin

    Harbor12345

    运行 准备prepare 脚本

    运行 安装 install.sh 脚本

      

    新建项目(tag分类),取名,选择“公开”

    【成员】创建用户密码方便用户push镜像过来

    # 直接推送,会发现提示需要验证(就是刚刚创建的用户)

    注:推送镜像的时候一定要注意命名规则,镜像名字要叫如下方式才可push

    <Harbor服务器IP或域名>/<harbor项目名>/<自定义的镜像名>:<TAG>,例如:

    118.xxx.xxx.2/cka/c7:loki_v1 
    118.xxx.xxx.2/cka/busybox:latest

    # 登录用户

     

    # 拉取

    docker pull 118.xxx.xxx.2/cka/busybox

     

    限制容器资源

    目的:防止各个容器资源抢占

    Cgroup : linux 系统下的功能

    /etc/systemd/system/memload.service.d

    # 使用memload 来进行测试

     memload <数值>

    方法一: 创建容器的时候参数限制

    OOM : 内存溢出  需求内存超过限制内存值

      

    # 用来长时间占用cpu  测试

      

    # 查看某个命令运行在哪些CPU上 

     --cpuset-cpus=0  #指定创建的容器在哪个cpu上运行

      

      

    # 针对CPU和内存设定值修改方法

    docker update  

    --cpuset-cpus <使用的CPU核心ID>   e.g.   docker update bbox_t1 --cpuset-cpus 10-15 ## 你要确定你有这么多核心的cpu才能设置这个值

    --memory-swap <这个值要大于内存值> ## 如果小于就会如下报错提示   e.g. docker update bbox_t1 --memory-swap 1024m

    # 内存限制小于内存的SWAP的限制值,请同步修改内存SWAP值。

     Memory limit should be smaller than already set memoryswap limit, update the memoryswap at the same time

    -m <内存大小>  e.g. docker update bbox_t1 -m 512m

      

    Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。

    block io 权重

    (1)参数说明

    • 默认情况下,所有容器能平等地读写磁盘,可以通过设置 --blkio-weight 参数来改变容器 block io 的优先级。 
    •  --blkio–weight 与 --cpu-shares 类似,设置的是相对权重值,默认为 500。

    限制 bps 和 iops 

    (1)bps 和 iops介绍:
    • bps 是 byte per second,每秒读写的数据量。 
    • iops 是 io per second,每秒 IO 的次数。
     
    (2)可通过以下参数控制容器的 bps 和 iops:
    • --device-read-bps:限制读某个设备的 bps。
    • --device-write-bps:限制写某个设备的 bps。
    • --device-read-iops:限制读某个设备的 iops。
    • --device-write-iops:限制写某个设备的 iops。

    ctop 命令研究(仅能检测容器的资源情况)

    sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-linux-amd64 -O /usr/local/bin/ctop

    sudo chmod +x /usr/local/bin/ctop

    # 界面展示

    # 基本常用命令  e 进入shell模式,l 进入log模式,o查看容器ip和资源信息,q退出

    监控容器 

    docker stats  # 监控容器基本信息

    # 原理读取物理机这些目录

     cadvisor  # google 建立一个监控容器,查看其他容器资源消耗

    scope 工具: Weave是由Zett.io公司开发的,它能够创建一个虚拟网络,用于连接部署在多台主机上的Docker容器,这样容器就像被接入了同一个网络交换机,那些使用网络的应用程序不必去配置端口映射和链接等信息。外部设备能够访问Weave网络上的应用程序容器所提供的服务,同时已有的内部系统也能够暴露到应用程序容器上。Weave能够穿透防火墙并运行在部分连接的网络上,另外,Weave的通信支持加密,所以用户可以从一个不受信任的网络连接到主机。

    cadvisor:  为了解决docker stats的问题(存储、展示),谷歌开源的cadvisor诞生了,cadvisor不仅可以搜集一台机器上所有运行的容器信息,还提供基础查询界面和http接口,方便其他组件如Prometheus进行数据抓取

  • 相关阅读:
    vue-awesome-swiper 子项目内容高度适配问题
    ajax的原理及应用
    display:none opacity:0以及visibility:hidden的区别
    javascript 创建型设计模式
    圣杯布局和双飞翼布局
    javascript->对象继承
    js 宏任务和微任务
    android->按钮底部定位上移
    ios移动端开发的坑
    jvm系列 (五) ---类加载机制
  • 原文地址:https://www.cnblogs.com/Cong0ks/p/14458321.html
Copyright © 2011-2022 走看看