首页 文章 精选 留言 我的

精选列表

搜索[技术极客],共10008篇文章
优秀的个人博客,低调大师

容器技术|Docker三剑之docker-swarm

docker-swarm简介 Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。 swarm集群提供给用户管理集群内所有容器的操作接口与使用一台Docker主机基本相同。 Swarm集群目前有两个版本:V1、V2 1、Swarm v1它是master-slave架构。需要通过服务发现来选举出管理节点,其它各个节点通过运行agent来接受管理节点的统一管理 2、Swarm v2集群是自动通过Raft协议分布式选举出管理节点,不需要配置发现服务,从而避免发现服务的单点故障问题。且它自带了DNS负载均衡和对外部负载均衡机制的支持 Swarm的基本架构如下图所示 Swarm一些概念说明 1、Swarm 使用swarmkit嵌入docker Engine中的集群管理和编排功能。docker容器初始化启动的一种模式 2、Node 节点,是一个已加入到docker swarm集群中的一个容器实例。 3、Service 服务主要是在工作节点上执行任务,创建服务时,需要指定容器的镜像。 4、Task 任务是在容器中执行的命令 Swarm 工作方式 1、节点 2、服务、任务、容器 3、任务与调度 4、服务副本与全局服务 Swarm 调度策略 Swarm在scheduler节点(leader 节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random. 1)Random 顾名思义,就是随机选择一个 Node 来运行容器,一般用作调试用,spread 和 binpack 策略会根据各个节点的可用的 CPU, RAM 以及正在运行的容器的数量来计算应该运行容器的节点。 2)Spread 在同等条件下,Spread 策略会选择运行容器最少的那台节点来运行新的容器,binpack 策略会选择运行容器最集中的那台机器来运行新的节点。使用 Spread 策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。 3)Binpack Binpack 策略最大化的避免容器碎片化,就是说 binpack 策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在一个节点上面。 Swarm Cluster模式的特性 1)批量创建服务 建立容器之前先创建一个 overlay 的网络,用来保证在不同主机上的容器网络互通的网络模式 2)强大的集群的容错性 当容器副本中的其中某一个或某几个节点宕机后,cluster 会根据自己的服务注册发现机制,以及之前设定的值–replicas n,在集群中剩余的空闲节点上,重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的 load balance 依旧好使! 不难看出,docker service 其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster 会持续检测服务的健康状态并维护集群的高可用性。 3)服务节点的可扩展性 Swarm Cluster不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过 scale参数即可复制出新的副本出来。仔细观察的话,可以发现所有扩展出来的容器副本都 run 在原先的节点下面,如果有需求想在每台节点上都 run 一个相同的副本,方法其实很简单,只需要在命令中将”–replicas n”更换成”–mode=global”即可!复制服务(–replicas n)将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“–replicas 3”。全局服务(–mode=global)适用于集群内全部可用节点上的服务任务,例如“–mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。 4)调度机制 所谓的调度其主要功能是 cluster 的 server 端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。 Swarm cluster的创建过程 1)发现 Docker 集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化 2)初始化内部调度(scheduler)模块 3)创建并启动 API 监听服务模块 一旦创建好这个 cluster,就可以用命令 docker service 批量对集群内的容器进行操作,在启动容器后,docker 会根据当前每个 swarm 节点的负载判断,在负载最优的节点运行这个 task 任务,用”docker service ls” 和”docker service ps + taskID”可以看到任务运行在哪个节点上。容器启动后,有时需要等待一段时间才能完成容器创建。 Swarm命令行说明 dockerswarm:集群管理 init#初始化集群 join#将节点加入集群 join-token#管理加入令牌 leave#从集群中删除某个节点,强制删除加参数--force update#更新集群 unlock#解锁集群 dockernode:节点管理, demote#将集群中一个或多个节点降级 inspect#显示一个或多个节点的详细信息 ls#列出集群中的节点 promote#将一个或多个节点提升为管理节点 rm#从集群中删除停止的节点,--force强制删除参数 ps#列出一个或多个节点上运行的任务 update#更新节点 dockerservice:服务管理, create#创建一个新的服务 inspect#列出一个或多个服务的详细信息 ps#列出一个或多个服务中的任务信息 ls#列出服务 rm#删除一个或多个服务 scale#扩展一个或多个服务 update#更新服务 dockerstack/deploy:试验特性,用于多应用部署 安装布署swarm集群服务 1、修改主机名,配置hosts文件 [root@manager~]#cat>>/etc/hosts<<EOF 192.168.22.177manager 192.168.22.175node1 192.168.22.178node2 EOF [root@manager~]#tail-3/etc/hosts 192.168.22.177manager 192.168.22.175node1 192.168.22.178node2 [root@manager~]#pingnode1 PINGnode1(192.168.22.175)56(84)bytesofdata. 64bytesfromnode1(192.168.22.175):icmp_seq =1ttl=64time=3.64ms 64bytesfromnode1(192.168.22.175):icmp_seq=2ttl=64time=1.64ms ^C ---node1pingstatistics--- 2packetstransmitted,2received,0%packetloss,time1006ms rttmin/avg/max/mdev=1.648/2.644/3.641/0.997ms [root@manager~]#pingnode2 PINGnode2(192.168.22.178)56(84)bytesofdata. 64bytesfromnode2(192.168.22.178):icmp_seq =1ttl=64time=9.70ms 64bytesfromnode2(192.168.22.178):icmp_seq=2ttl=64time=1.95ms ^C ---node2pingstatistics--- 2packetstransmitted,2received,0%packetloss,time1003ms rttmin/avg/max/mdev=1.951/5.826/9.701/3.875ms #node1node2配置同上一致即可 2、安装docker环境 具体安装过程参考前面的文章 配置docker [root@manager~]#vim/etc/sysconfig/docker #/etc/sysconfig/docker #Modifytheseoptionsifyouwanttochangethewaythedockerdaemonruns OPTIONS='-H0.0.0.0:2375-Hunix:///var/run/docker.sock--selinux-enabled--log-driver=journald--signature-verification=false' #所有节点加上上面标记的部分,开启2375端口 [root@manager~]#systemctlrestartdocker [root@manager~]#ps-ef|grepdocker root119811110:55?00:00:00/usr/bin/dockerd-current--add-runtimedocker-runc=/usr/libexec/docker/docker-runc-current--default-runtime=docker-runc--exec-optnative.cgroupdriver=systemd--userland-proxy-path=/usr/libexec/docker/docker-proxy-current--init-path=/usr/libexec/docker/docker-init-current--seccomp-profile=/etc/docker/seccomp.json-H0.0.0.0:2375-Hunix:///var/run/docker.sock--selinux-enabled--log-driver=journald--signature-verification=false--storage-driveroverlay2 root1198611981010:55?00:00:00/usr/bin/docker-containerd-current-lunix:///var/run/docker/libcontainerd/docker-containerd.sock--metrics-interval=0--start-timeout2m--state-dir/var/run/docker/libcontainerd/containerd--shimdocker-containerd-shim--runtimedocker-runc--runtime-args--systemd-cgroup=true root1207611823010:55pts/000:00:00grep--color=autodocker [root@manager~]#lsof-i:2375 COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAME dockerd-c11981root5uIPv6418290t0TCP*:2375(LISTEN) 3、所有节点下载swarm镜像文件 [root@manager~]#dockerpullswarm Usingdefaulttag:latest Tryingtopullrepositorydocker.io/library/swarm... latest:Pullingfromdocker.io/library/swarm d85c18077b82:Pullcomplete 1e6bb16f8cb1:Pullcomplete 85bac13497d7:Pullcomplete Digest:sha256:406022f04a3d0c5ce4dbdb60422f24052c20ab7e6d41ebe5723aa649c3833975 Status:Downloadednewerimagefordocker.io/swarm:latest [root@manager~]#dockerimages REPOSITORYTAGIMAGEIDCREATEDSIZE docker.io/swarmlatestff454b4a0e8412daysago12.7MB 4、创建swarm并初始化 [root@manager~]#dockerswarminit--advertise-addr192.168.22.177 Swarminitialized:currentnode(elyfa6h1lx5o2s98une5vas4x)isnowamanager. Toaddaworkertothisswarm,runthefollowingcommand: dockerswarmjoin\ --tokenSWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya\ 192.168.22.177:2377 Toaddamanagertothisswarm,run'dockerswarmjoin-tokenmanager'andfollowtheinstructions. #执行上面的命令后,当前的服务器就加入到swarm集群中,同时会产生一个唯一的token值,其它节点加入集群时需要用到这个token。 #--advertise-addr表示swarm集群中其它节点使用后面的IP地址与管理节点通讯,上面也提示了其它节点如何加入集群的命令。 5、查看下当前的信息 [root@manager~]#dockerinfo Containers:0 Running:0 Paused:0 Stopped:0 Images:1 ServerVersion:1.13.1 StorageDriver:overlay2 BackingFilesystem:xfs Supportsd_type:true NativeOverlayDiff:true LoggingDriver:journald CgroupDriver:systemd Plugins: Volume:local Network:bridgehostmacvlannulloverlay **Swarm:active NodeID:elyfa6h1lx5o2s98une5vas4x IsManager:true ClusterID:vi716cgvw33gzicrfqopasf9p Managers:1 Nodes:1 Orchestration: TaskHistoryRetentionLimit:5 Raft: SnapshotInterval:10000 NumberofOldSnapshotstoRetain:0 HeartbeatTick:1 ElectionTick:3 Dispatcher: HeartbeatPeriod:5seconds CAConfiguration: ExpiryDuration:3months NodeAddress:192.168.22.177 ManagerAddresses: 192.168.22.177:2377 Runtimes:docker-runcrunc DefaultRuntime:docker-runc InitBinary:/usr/libexec/docker/docker-init-current containerdversion:(expected:aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1) runcversion:e9c345b3f906d5dc5e8100b05ce37073a811c74a(expected:9df8b306d01f59d3a8029be411de015b7304dd8f) initversion:5b117de7f824f3d3825737cf09581645abbe35d4(expected:949e6facb77383876aeff8a6944dde66b3089574) SecurityOptions: seccomp WARNING:You'renotusingthedefaultseccompprofile Profile:/etc/docker/seccomp.json KernelVersion:3.10.0-693.el7.x86_64 OperatingSystem:CentOSLinux7(Core) OSType:linux Architecture:x86_64 NumberofDockerHooks:3 CPUs:1 TotalMemory:2.238GiB Name:manager ID:653Y:7CME:GFPW:35SX:IGZL:UJP7:YSPZ:4OMV:J4EV:Z6FS:WFW2:YYHS DockerRootDir:/var/lib/docker DebugMode(client):false DebugMode(server):false Registry:https://index.docker.io/v1/ WARNING:bridge-nf-call-ip6tablesisdisabled Experimental:false InsecureRegistries: 127.0.0.0/8 LiveRestoreEnabled:false Registries:docker.io(secure) [root@manager~]#dockernodels IDHOSTNAMESTATUSAVAILABILITYMANAGERSTATUS elyfa6h1lx5o2s98une5vas4x*managerReadyActiveLeader #当前节点的信息,这个*表示当前连接在这个节点上 6、将node1,node2加入到集群中 [root@node1~]#dockerswarmjoin--tokenSWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya192.168.22.177:2377 Thisnodejoinedaswarmasaworker. [root@node2~]#dockerswarmjoin--tokenSWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya192.168.22.177:2377 Thisnodejoinedaswarmasaworker. #如果加入集群时报错如下 [root@node1~]#dockerswarmjoin--tokenSWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya192.168.22.177:2377 Errorresponsefromdaemon:rpcerror:code=13desc=connectionerror:desc="transport:x509:certificatehasexpiredorisnotyetvalid" #注意服务器时间同步问题,解决即可。 7、管理节点查看集群节点状态 [root@manager~]#dockernodels IDHOSTNAMESTATUSAVAILABILITYMANAGERSTATUS elyfa6h1lx5o2s98une5vas4x*managerReadyActiveLeader tcuv2p8wd6rvmwg39pdav5ozknode1ReadyActive twytwc5dlp77vu1b7cakks9w2node2ReadyActive #swarm集群中node的AVAILABILITY状态有两种:Active、drain。其中actice状态的节点可以接受管理节点的任务指派;drain状态的节点会结束任务,也不会接受管理节点的任务指派,节点处于下线状态。 [root@manager~]#dockernodeupdate--availabilitydrainnode2 node2 [root@manager~]#dockernodels IDHOSTNAMESTATUSAVAILABILITYMANAGERSTATUS elyfa6h1lx5o2s98une5vas4x*managerReadyActiveLeader tcuv2p8wd6rvmwg39pdav5ozknode1ReadyActive twytwc5dlp77vu1b7cakks9w2node2ReadyDrain [root@manager~]#dockernodeupdate--availabilityactivenode2 node2 [root@manager~]#dockernodels IDHOSTNAMESTATUSAVAILABILITYMANAGERSTATUS elyfa6h1lx5o2s98une5vas4x*managerReadyActiveLeader tcuv2p8wd6rvmwg39pdav5ozknode1ReadyActive twytwc5dlp77vu1b7cakks9w2node2ReadyActive #在manager节点上查看状态信息 [root@manager~]#dockernodeinspectself [ { "ID":"elyfa6h1lx5o2s98une5vas4x", "Version":{ "Index":9 }, "CreatedAt":"2018-06-14T15:01:19.850821157Z", "UpdatedAt":"2018-06-14T15:01:20.472379584Z", "Spec":{ "Role":"manager", "Availability":"active" }, "Description":{ "Hostname":"manager", "Platform":{ "Architecture":"x86_64", "OS":"linux" }, "Resources":{ "NanoCPUs":1000000000, "MemoryBytes":2402566144 }, "Engine":{ "EngineVersion":"1.13.1", "Plugins":[ { "Type":"Network", "Name":"bridge" }, { "Type":"Network", "Name":"host" }, { "Type":"Network", "Name":"macvlan" }, { "Type":"Network", "Name":"null" }, { "Type":"Network", "Name":"overlay" }, { "Type":"Volume", "Name":"local" } ] } }, "Status":{ "State":"ready", "Addr":"127.0.0.1" }, "ManagerStatus":{ "Leader":true, "Reachability":"reachable", "Addr":"192.168.22.177:2377" } } ] Swarm 的Web管理 [root@manager~]#dockerrun-d-p9000:9000-v/var/run/docker.sock:/var/run/docker.sockportainer/portainer Unabletofindimage'portainer/portainer:latest'locally Tryingtopullrepositorydocker.io/portainer/portainer... latest:Pullingfromdocker.io/portainer/portainer d1e017099d17:Pullcomplete 0d90a7ef0797:Pullcomplete Digest:sha256:2933caa6e578e94b5d91429ea7f47ae9741ee11b71d7cb740e76c5f234cc1d87 Status:Downloadednewerimagefordocker.io/portainer/portainer:latest 798b3bea009792321519f5b7144e357ce9c5cea3b9341b5276a4d29f7571684a [root@manager~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 798b3bea0097portainer/portainer"/portainer"6secondsagoUp5seconds0.0.0.0:9000->9000/tcpamazing_snyder 浏览器访问 docker-swarm布署服务 1、布署服务前创建于个用于集群内不同主机之间容器通信的网络 [root@manager~]#dockernetworkcreate-doverlaydockernet pmn1fi6lj421hn1nk7652m41h [root@manager~]#dockernetworkls NETWORKIDNAMEDRIVERSCOPE d913c7a275febridgebridgelocal c737cf269524docker_gwbridgebridgelocal pmn1fi6lj421dockernetoverlayswarm eac1d68d35d7hosthostlocal wxshzhdvq52yingressoverlayswarm c5986aec6119nonenulllocal 2、创建服务(nginx为例) [root@manager~]#dockerservicecreate--replicas1--networkdockernet--namenginx-cluster-p80:80nginx k7lupo9xu0cnd5ng1g4f7i7jx #--replicas指定副本数量 [root@manager~]#dockerservicels IDNAMEMODEREPLICASIMAGE k7lupo9xu0cnnginx-clusterreplicated1/1nginx:latest [root@manager~]#dockerservicepsnginx-cluster IDNAMEIMAGENODEDESIREDSTATECURRENTSTATEERRORPORTS 7t7xjpmao533nginx-cluster.1nginx:latestmanagerRunningRunning17secondsago [root@manager~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES a9d78079fdc7nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx-g'daemon..."22secondsagoUp22seconds80/tcpnginx-cluster.1.7t7xjpmao5335zaa8wp0c896a 3、在线动态扩容服务 [root@manager~]#dockerservicescalenginx-cluster=5 nginx-clusterscaledto5 [root@manager~]#dockerservicepsnginx-cluster IDNAMEIMAGENODEDESIREDSTATECURRENTSTATEERRORPORTS 7t7xjpmao533nginx-cluster.1nginx:latestmanagerRunningRunning2hoursago vitsgxpdf3bnnginx-cluster.2nginx:latestmanagerRunningRunning2secondsago o9w529mmttswnginx-cluster.3nginx:latestnode1RunningPreparing2secondsago cfz8dkx9p6ihnginx-cluster.4nginx:latestnode2RunningPreparing2secondsago 9p35iunijoronginx-cluster.5nginx:latestnode2RunningPreparing2secondsago #从输出结果可以看出已经将服务动态扩容至5个,也就是5个容器运行着相同的服务 [root@node2~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES f3a4fb24480anginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx-g'daemon..."3minutesagoUp3minutes80/tcpnginx-cluster.5.9p35iunijorol1d2ikhyj11oi f8b0b2e514ebnginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx-g'daemon..."3minutesagoUp3minutes80/tcpnginx-cluster.4.cfz8dkx9p6ih40lwwwvd96xdg #登录node2查看正在运行的容器,发现与管理节点上显示的结果相同,node2上运行两个容器 4、节点故障 [root@manager~]#dockerservicepsnginx-cluster IDNAMEIMAGENODEDESIREDSTATECURRENTSTATEERRORPORTS 7t7xjpmao533nginx-cluster.1nginx:latestmanagerRunningRunning2hoursago vitsgxpdf3bnnginx-cluster.2nginx:latestmanagerRunningRunning10minutesago f13cun1wyxltnginx-cluster.3nginx:latestmanagerRunningRunning9minutesago q60fo5mja1ab\_nginx-cluster.3nginx:latestnode1ShutdownFailed9minutesago"startingcontainerfailed:sh…" mao4htxp7afr\_nginx-cluster.3nginx:latestnode1ShutdownFailed9minutesago"startingcontainerfailed:sh…" fhiecco742y4\_nginx-cluster.3nginx:latestnode1ShutdownFailed10minutesago"startingcontainerfailed:sh…" 8qp5kryo62ha\_nginx-cluster.3nginx:latestnode1ShutdownFailed10minutesago"startingcontainerfailed:sh…" cfz8dkx9p6ihnginx-cluster.4nginx:latestnode2RunningRunning9minutesago 9p35iunijoronginx-cluster.5nginx:latestnode2RunningRunning9minutesago #如果集群中节点发生故障,会从swarm集群中被T除,然后利用自身的负载均衡及调度功能,将服务调度到其它节点上 5、其它常用命令介绍 除了上面使用scale来实现在线动态扩容、缩容之外,还可以使用update来对服务进行调整 [root@manager~]#dockerservicels IDNAMEMODEREPLICASIMAGE k7lupo9xu0cnnginx-clusterreplicated5/5nginx:latest [root@manager~]#dockerserviceupdate--replicas2nginx-cluster nginx-cluster [root@manager~]#dockerservicels IDNAMEMODEREPLICASIMAGE k7lupo9xu0cnnginx-clusterreplicated2/2nginx:latest #将服务缩减到2个 [root@manager~]#dockerserviceupdate--imagenginx:newnginx-cluster #更新服务的镜像版本 [root@manager~]#dockerservice--help Usage:dockerserviceCOMMAND Manageservices Options: --helpPrintusage Commands: createCreateanewservice inspectDisplaydetailedinformationononeormoreservices lsListservices psListthetasksofaservice rmRemoveoneormoreservices scaleScaleoneormultiplereplicatedservices updateUpdateaservice Run'dockerserviceCOMMAND--help'formoreinformationonacommand. [root@manager~]#dockerrmnginx-cluster #将所有节点上的所有容器全部删除,任务也将全部删除 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:744677563 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

优秀的个人博客,低调大师

无限分类

$arr = array( 0=>[ 'id'=>1, 'name'=>'科技', 'pid'=>0, ], 1=>[ 'id'=>2, 'name'=>'人工智能', 'pid'=>1, ], 2=>[ 'id'=>3, 'name'=>'美食', 'pid'=>0 ], 3=>[ 'id'=>4, 'name'=>'重庆小面', 'pid'=>3 ], 4=>[ 'id'=>5, 'name'=>'机器人', 'pid'=>2 ] ); public function category($arr,$pid=0,$level=0){ //定义一个静态变量,存储一个空数组,用静态变量,是因为静态变量不会被销毁,会保存之前保留的值,普通变量在函数结束时,会死亡,生长周期函数开始到函数结束,再次调用重新开始生长 //保存一个空数组 static $list=array(); //通过遍历查找是否属于顶级父类,pid=0为顶级父类, foreach($arr as $value){ //进行判断如果pid=0,那么为顶级父类,放入定义的空数组里 if($value['pid']==$pid){ //添加空格进行分层 $arr['level']=$level; $list[]=$value; //递归点,调用自身,把顶级父类的主键id作为父类进行再调用循环,空格+1 self::category($arr,$value['id'],$level+1); } } return $list;//递归出口 } $list = category($arr,0,0);

优秀的个人博客,低调大师

Docker简入门

一、Docker概述 Docker通过一个包括应用程序运行时所需的一切的可执行镜像启动容器,包括配置有代码、运行时、库文件、环境变量和配置文件等。 1.文件系统隔离:每个容器都有自己得root文件系统。 2.进程隔离:每个容器都运行再自己得进程环境中。 3.容器间得虚拟网络接口和IP地址都是分开的。 4.资源隔离和分组:使用cgroup将CPU和内存之类的资源独立分配给每个Docker容器。 5.写时复制:文件系统都是通过写时复制创建的,这就意味着文件系统是分层的、快速的,并且占用磁盘空间小。 6.日志:容器产生的STDOUT、STDIN和STDERR这些IO流都会被收集并记入日志,用来进行日志分析和故障排除。 7.交互式shell:用户可以创建一个伪tty终端、将其连接到STDIN,为容器提供一个交互式shell。 8.灵活性:大多数应用程序均能被装箱。 9.轻量级:容器利用并共享主机内核。 10.可交互:可以即时的更新和升级。 11.可移植:一处构建,到处运行。 12.可扩展性:可以增加和分发容器副本。 二、Docker容器的安装与入门 1.Docker的安装过程很简单,本次试验是在CentOS7.4中进行的,因此不存在内核版本及系统平台不支持的情况。简单的安装配置如下: [root@ChatDevOps ~]# yum -y install docker [root@ChatDevOps ~]# docker --version Docker version 1.13.1, build 94f4240/1.13.1 [root@ChatDevOps ~]# systemctl start docker [root@ChatDevOps ~]# systemctl status docker [root@ChatDevOps ~]# systemctl enable docker [root@ChatDevOps ~]# docker info 2.docker info:返回所有容器和镜像的数量、Docker使用的执行驱动和存储驱动及Docker的基本配置。 [root@ChatDevOps ~]# docker info Containers: 15 Running: 1 Paused: 0 Stopped: 14 Images: 4 Server Version: 1.13.1 ... ... 3.docker images:列出当前系统中本地镜像。例如,列出本地镜像中REPOSITORY为ubuntu的镜像: [root@ChatDevOps ~]# docker images ubuntu REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/ubuntu latest 452a96d81c30 3 weeks ago 79.6 MB 4.docker ps:列出所有正在运行的容器。 [root@ChatDevOps ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e93e508dbc38 centos "/bin/bash" 2 hours ago Up 2 minutes fervent_turing 加上选项-a则列出的是所有的容器,包括正在运行的和未运行的。加选项-n则代表列出前n个容器,n后面跟需要列出的容器的个数。 [root@ChatDevOps ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dfd4fe17d6ce httpd "/bin/bash" 2 hours ago Exited (0) 43 minutes ago stoic_gates 7b4ddbb18811 ubuntu "/bin/bash" 2 hours ago Exited (0) 43 minutes ago priceless_bassi e93e508dbc38 centos "/bin/bash" 2 hours ago Up About a minute fervent_turing [root@ChatDevOps ~]# docker ps -n 10 docker run:创建一个新的容器并运行一个命令。 [root@ChatDevOps ~]# docker run --name ivandu -i -t centos /bin/bash [root@009c8df5e30d /]# 上面例子中创建了一个名为ivandu的容器。Docker首先检查本地是否存在镜像centos,如果不存在,则会连接到Docker官方维护的Docker Hub Registry,查看Docker Hub是否存在该镜像,如果存在则下载该镜像并保存到本地宿主机。选项-i表示容器的stdin是开启的,选项-t表示为要被创建的容器分配一个伪tty终端,centos表示创建这个容器使用的是centos这个镜像,/bin/bash表示容器创建完成之后执行容器中的该命令。选项-d则会将容器置于后台运行。 5.docker start:启动一个容器,可以是容器的ID和名称(NAMES)。 [root@ChatDevOps ~]# docker start dfd4fe17d6ce dfd4fe17d6ce [root@ChatDevOps ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dfd4fe17d6ce httpd "/bin/bash" 4 hours ago Up 10 seconds 80/tcp stoic_gates e93e508dbc38 centos "/bin/bash" 4 hours ago Up 2 hours fervent_turing [root@ChatDevOps ~]# docker start stoic_gates stoic_gates [root@ChatDevOps ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dfd4fe17d6ce httpd "/bin/bash" 4 hours ago Up 8 minutes 80/tcp stoic_gates e93e508dbc38 centos "/bin/bash" 5 hours ago Up 2 hours fervent_turing 同理,docker stop及docker restart的用法大同小异。 6.docker attach:可以进入一个已经在运行的容器。命令后面的容器id也可以换成容器名称。需要注意的是,如果退出容器的shell,容器也会随之停止运行。 [root@ChatDevOps ~]# docker start 7b4ddbb18811 7b4ddbb18811 [root@ChatDevOps ~]# docker attach 7b4ddbb18811 root@7b4ddbb18811:/# cat /etc/issue Ubuntu 18.04 LTS \n \l root@7b4ddbb18811:/# exit [root@ChatDevOps ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7.docker rm:删除一个已经停止的容器。如果这个容器正在运行,需要先停止该容器的运行或者使用选项-f进行强制删除。 [root@ChatDevOps ~]# docker rm -f 009c8df5e30d 009c8df5e30d 一次性删除所有的容器: [root@ChatDevOps ~]# docker rm `docker ps -a -q` 8.docker logs:获取容器的日志,我们可以通过该日志了解容器内部正在进行什么样的操作。可以跟选项-f,类似于tail命令,显示日志最后部分。选项-t则为每条日志加上了时间戳。 [root@ChatDevOps ~]# docker logs -tf dfd4fe17d6ce 2018-05-22T05:35:24.196281000Z root@dfd4fe17d6ce:/usr/local/apache2# exit root@dfd4fe17d6ce:/usr/local/apache2# 2018-05-22T08:56:00.809591000Z root@dfd4fe17d6ce:/usr/local/apache2# ls 2018-05-22T08:56:00.811456000Z bin build cgi-bin conf error htdocs icons include logs modules 2018-05-22T08:56:06.779932000Z root@dfd4fe17d6ce:/usr/local/apache2# ps -aux 2018-05-22T08:56:06.782810000Z USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 2018-05-22T08:56:06.783173000Z root 1 0.0 0.1 20236 1980 ? Ss 08:40 0:00 /bin/bash 2018-05-22T08:56:06.783462000Z root 6 0.0 0.1 17492 1144 ? R+ 08:56 0:00 ps -aux 2018-05-22T08:56:19.520653000Z root@dfd4fe17d6ce:/usr/local/apache2# httpd -k start 2018-05-22T08:56:19.550996000Z AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message 2018-05-22T08:57:01.656035000Z root@dfd4fe17d6ce:/usr/local/apache2# cat /etc/issue 2018-05-22T08:57:01.656305000Z Debian GNU/Linux 8 \n \l 2018-05-22T08:57:01.656609000Z 2018-05-22T08:57:07.888609000Z root@dfd4fe17d6ce:/usr/local/apache2# exit 2018-05-22T08:57:07.888981000Z exit 9.docker top:查看正在运行的容器内部的进程运行情况。停止的容器并不支持此法进行查看。 [root@ChatDevOps ~]# docker start 7bc9a41a53cd 7bc9a41a53cd [root@ChatDevOps ~]# docker top 7bc9a41a53cd UID PID PPID C STIME TTY TIME CMD root 6869 6855 0 17:26 pts/0 00:00:00 /bin/bash 10.docker exec:在一个运行中的容器内部执行命令或者进入一个正在运行的容器内。选项-d表示命令在后台执行,-d后跟容器名和要执行的命令。也可以通过选项-i和-t搭配使用进入一个正在运行的容器,与attach不同的是,如果退出容器的shell,该容器并不会停止运行。 [root@ChatDevOps ~]# docker exec -d 7bc9a41a53cd touch /home/ChatDevOps.log [root@ChatDevOps ~]# docker exec -i -t 7bc9a41a53cd /bin/bash [root@7bc9a41a53cd /]# ll /home/ChatDevOps.log -rw-r--r--. 1 root root 0 May 22 09:40 /home/ChatDevOps.log 11.docker inspect:返回一个低水平的Docker对象信息。可以用选项-f或--format来获取选定结果。支持完整的go语音模板,可以充分利用go语音的优势。 [root@ChatDevOps ~]# docker inspect dfd4fe17d6ce [ { "Id": "dfd4fe17d6ce1e17ca55e741c6979b16b32383c909ad2145f1c1fcb231612ecf", "Created": "2018-05-22T04:03:10.289044219Z", "Path": "/bin/bash", "Args": [], "State": { ... ... [root@ChatDevOps ~]# docker inspect --format='{{.State.Running}}' dfd4fe17d6ce false [root@ChatDevOps ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' 7bc9a41a53cd 172.17.0.2 12.docker kill:杀死一个或多个正在运行的容器。 [root@ChatDevOps ~]# docker kill 7bc9a41a53cd 7bc9a41a53cd 三、总结 通过本篇,我们了解了Docker的优点及简单入门知识。文中并未进行大量详细的原理性的内容阐述,主要通过实践来演示一入门常用的一些命令及其使用注意事项。以此来加深对Docker原理的理解。本篇博文是来北京工作后的第一篇文章,纪念一下。

优秀的个人博客,低调大师

梯度下降简入门

导 语 梯度下降及其变体被用作训练过程的关键部分在机器学习中广泛使用。梯度下降中的“梯度”是指单变量导数的推广形式,即多元变量求导。 梯度下降法是解决“优化问题”的迭代方法,其中优化问题是指围绕寻找函数的全局最小值或最大值而展开的数学问题。我们将很快看到,对于简单的优化问题可以不用梯度下降。当事情变得复杂时,我们则需要用诸如梯度下降之类的迭代法,当然和神经网络相关的优化问题确实足够复杂。 01 重新回顾优化问题 假设你已经购买了200米的铁丝网。您想使用此围栏为羊群创建一个矩形牧场。如何确定使牧场内部面积最大化时,牧场对应的长度和宽度? 使用标准的分析方法来解决这个问题,我们首先要写一个方程式来表示我们的问题。首先,我们知道两件事: area(面积)=length(长度)*width(宽度)(2 * length)+(2 * width)= 200 但是我们想用一个变量而不是两个变量来表示面积,所以我们可以求解这两个方程中的第二个变量的宽度: 2 * width = 200–2 * lengthwidth = [200-2 * length] / 2width = 100 - length 现在我们可以用100- length代替width,则: area= length * [100–length]area = f(length)=100 * length- length² 取面积的导数: area’=100-2*length;length=50 现在,我们找到了函数的“临界点”,即一阶导数等于零时对应的长度,当然函数在该点处的斜率也为零。我们关心这种值,因为它们是唯一能对应函数最小值或函数最大值的数。在临界点处,该点两侧的值可能都小于或都大于临界点处的值。因为函数中该点外的斜率都不为零,这意味着临界点上一边的点对应的面积将小于该临界点对应的面积,而另一边的点对应的面积将大于该临界点对应的面积。也就是说,该函数在非临界点处正在增加或减少,因此不能为最大值或最小值。 area’=100-2*length=0-->length=50 这表明如果存在全局最大值或最小值,则必须在长度= 50时发生。也就是说,如果矩形的长度存在最佳选择,则为50米。可能存在临界点既不是最小值也不是最大值,所以应该检测已发现的临界点确实是最值。在微积分课程中,有相关的检验方法(比如二阶导数检验),现在用更简单的方法(类似梯度下降法)来解决该问题,比如在临界点长度= 50的左右两侧测试2个点。 f(49)= 4900–2401 = 2499f(50)= 5000–2500 = 2500f(51)= 5100–2601 = 2499 这并不能确认矩阵面积最大时对应长度值就是50,或者某些时候有比50更好的点,不过这种近似的方法最终将应用于训练模型。对于这个简单的问题,通过绘制函数了解该方法和实际的误差: 02 梯度下降—迭代式猜测 那么这与梯度下降方法有什么关系呢?梯度下降方法比较粗糙,就像刚才所做的那些不精确的猜测一样。看上去它是比随机猜测稍强一点的显得杂乱的体系,不过它将最终成为我们解决围栏问题的方法: 猜测围栏的最佳长度 计算此时的梯度值 根据梯度的值,调整猜测 重复猜测直到满足条件则终止 假设我们随机选取57当作长度的第一个猜测值,在57处,面积函数的导数为: f(57)=100*57 - 57*57 = 2451f'(57)=100–2*(57)=-14 ‍ length = 57处的斜率不为0,因此不是临界点。此外斜率为-14表示如果将长度增加 1,则面积将减小 14(假设函数的斜率不变)。梯度下降使用此值作为进行下一个猜测的指导。比如要增加面积的值,因为斜率是负数,所以应该57基础上减小长度,以此增加面积的值。 然而即使知道当前应该减少length的值,也没有先验的方法可以确切地知道“合适”的数来调整我们的当前的猜测(length=57)。在像TensorFlow这样的软件包中,我们用来调整当前length的快慢将由一个称为“学习率”的超参数控制,可以在训练时设置该参数。提高学习率将导致梯度下降对当前当前length调整很快;减小学习率会导致梯度下降对当前当前length调整较慢。现在假设将当前length减少3,虽然有点武断,但实际上效果可以接受。 57–3 = 54f(54)= 5400–(54²)-->f(54)= 5400–2916 -->f(54)= 2484 2484大于2451,说明找到的面积比上次大。再次使用导数来检查是否处于临界点,如果不是,则调整猜测值: f'(54)= 100–2 * 54 = 100–108 = -8 我们的当前猜测值(54)仍然很大,斜率-8低于-14,应该适当减缓对当前猜测值的更改幅度,比如在54基础上减少2,则: f(52)= 5200–52² --> f(52)= 5200–2704 -->f(52)= 2496 我们将重复此过程,直到找到一个临界点。或者直到f'(length)的值非常接近零,才能认为length已足够接近临界点。手工完成此过程是重复且繁琐的,但是计算机善于解决重复繁琐的任务。通俗点说,将像在爬山和滚球,一直沿着抛物线上升,直到无法进一步上升为止。 请注意导数(蓝色),它在最大值的右边是负数,在最大值的左边是正数。在这种情况下,很容易找到最大值。 由于试图找到面积的最大值,上面的示例称之为“梯度上升”更好。在梯度下降中,每次计算梯度值时都将其相反数。 马上将提到的梯度下降和在神经网络里面用到的梯度下降有两个不一样的地方。首先,神经网络对应的函数比f(length)更复杂。我们的神经网络具有成千上万的可调参数,而其中f(length)只有一个。我们使用诸如梯度下降之类的迭代方法主要是因为神经网络模型非常复杂,而不是选用之前查找临界点时的分析过程。计算当前如此庞大规模的神经网络所表示的一般性的函数导数根本不可行。第二个区别是,在此示例中,有一个充当标准结果的实函数,并且发现了该函数的最佳值。在神经网络中,没有显式的函数;取而代之的是,我们尝试创建一个不存在标准结果的函数。 03 用于函数查找的梯度下降 在前面的示例中,使用梯度下降方法沿该曲线可以找到最佳值。在机器学习中,对于训练集中的数据,我们希望创建一条曲线来更好地拟合这些数据。回顾一下刚刚研究的围栏问题,将它转化为我们更倾向于用机器学习解决的问题。 我们从围栏数据库中收集了很多数据样本。我们数据集中的每个数据点的背景都是来自用100米围栏材料来建造矩形牧场。每个数据点有2个参数:围栏一侧的长度和围栏的面积。在这个问题中,不是尝试找到围栏的最佳长度,而是试图找到一个函数,该函数可以根据给定的边长来预测矩形围栏的面积。我们的输入数据如下所示: 看起来数据中有一个模式,我们可以使用机器学习来定义模式吗? 机器学习解决此问题的方法是认为:“看起来有点像某种数学函数,想知道到底是哪个函数?”,更进一步,我们猜测该函数是某种抛物线函数,则该函数的一般表达式是: F(x)=ax²+ bx 在数据集中已知x值和y值,现在我们将使用梯度下降法来找到a和b的最佳值。为此,我们引入了另一个函数--损失函数,并运行梯度下降以最小化损失函数。将F(x)当作“正在进行训练的函数”,其中x仍然是围栏一侧的长度,y是围栏的真实面积。单次预测的绝对误差为: L(x)= | F(x)- y | 我们需要给误差加上绝对值。如果不这样做且连续做两次预测,假设一次错了1000,另一次错了-1000,则两次错误刚好抵消,实际上这样一共错了两次。 最终我们会用这样的一个损失函数:平均绝对误差,它是数据集中所有的点对应L(x)的平均值。使用诸如均方误差之类的指标更为常见,但是不同的损失函数对不同的数据集。 假设我们随机选择权重的起始值:a = -2和b = 30。在对应的F(x)变为: L(x)= | -2x²+ 30x-y | 接下来的内容略带技巧性。我们想要调整a和b的值以最小化损失函数。因此我们需要计算损失函数对a和b的梯度(偏导数)。以前的函数中,x的值可以不断变化。但是这个问题里面,情况并非如此。x的值始终只是我们数据集中的某个固定值。因此单个数据点对应的损失函数为:L(a, b) = ax² + bx – y,其中x、y是常数。 使用平均绝对误差的损失函数为: L(a,b)=1/m*SUM(|F(a,b)—yi|)L(a,b)=(1 / m)* SUM(|axi²+ bxi — yi |) 其中xi和yi代表我们数据集中的单个数据点,而m是我们数据集中点的总数。这里有两个细节上的问题:一个是我们必须使用链式规则来计算涉及绝对值的梯度;另一个是绝对值函数在预测值恰好等于真实值的点上是不可求导的,并且。 如果平均绝对误差为0,可以通过停止计算梯度来解决不可导的问题。这是有实际意义的。如果我们在这个数据点上的预测值与实际值都符,那么就不需要用改善绝对误差的方式来调整模型: d | x |/ dx = 1,如果x为正d | x |/ dx = -1,如果x为负则损失函数对a、b求偏导数可以写成:L(a, b) = (1/m) * SUM( | axi² + bxi — yi | )L’_a(a, b) = (1 / m) * SUM( 1 * xi² ); F(xi) > yiL’_a(a, b) = (1 / m) * SUM( -1 * xi² ); F(xi) < yiL’_b(a, b) = (1 / m) * SUM( 1 * x ); F(xi) > yL’_b(a, b) = (1 / m) * SUM( -1 * x );F(xi) < yi 这些公式实际上为我们提供了一个非常简单的更新规则:如果我们的预测太小,则将a和b都增大。如果我们的预测太大,则将a和b都减小。 深刻地理解梯度下降以及优化损失函数的思路可以更好地理解过拟合之类的问题,同时它还可以帮助我们更好地了解神经网络训练的过程。 1 END 1 长 按 关 注 获取最新AI资讯与实战案例 实用AI客栈 小编微信号 : langu86 本文分享自微信公众号 - 实用AI客栈(gh_0b0b5e56231f)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

简模板语言实现

在项目中遇到这样一个功能,需要用户输入一段带参数的字符串模板,然后服务端根据一个上下文去解析它。查了一些资料发现了StrSubstitutor 这个小工具。其自带例子如下: Map valuesMap = HashMap(); valuesMap.put("animal", "quick brown fox"); valuesMap.put("target", "lazy dog"); String templateString = "The ${animal} jumped over the ${target}."; StrSubstitutor sub = new StrSubstitutor(valuesMap); String resolvedString = sub.replace(templateString

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册