¡¾±àÕߵϰ¡¿KubernetesÊÇGoogle¿ªÔ´µÄÈÝÆ÷¼¯Èº¹ÜÀíϵͳ£¬ÆäÌṩӦÓò¿Êð¡¢Î¬»¤¡¢
À©Õ¹»úÖÆµÈ¹¦ÄÜ¡£MesosÊÇApacheϵĿªÔ´·Ö²¼Ê½×ÊÔ´¹ÜÀí¿ò¼Ü£¬Ëü±»³ÆÎªÊÇ·Ö²¼Ê½ÏµÍ³µÄÄںˡ£Mesos×î³õÊÇÓɼÓÖÝ´óѧ²®¿ËÀû·ÖУµÄAMPLab¿ª·¢µÄ£¬ºóÔÚTwitterµÃµ½¹ã·ºÊ¹Óá£SwarmÊÇDocker¹«Ë¾ÔÚ2014Äê12Ô³õз¢²¼µÄÈÝÆ÷¹ÜÀí¹¤¾ß¡£ºÍSwarmÒ»Æð·¢²¼µÄDocker¹ÜÀí¹¤¾ß»¹ÓÐMachineÒÔ¼°Compose¡£ÎÒÃÇÀ´¿´ÏÂRancher¶ÔËüÃÇÓÐʲôÆÀ¼Û¡£

Rancher×îеİ汾ÔÚÔÓйٷ½±ê×¼±àÅŹ¤¾ßCattleµÄ»ù´¡ÉÏ£¬ÐÂÔöÖ§³ÖÆäËû¼¸ÖÖ³£ÓõıàÅÅÒýÇæ¡£ÐÂÔöÖ§³ÖµÄ±àÅÅÒýÇæ°üÀ¨Swarm£¨DockerδÀ´±¾µØ±àÅÅÒýÇæ£©¡¢KubernetesºÍMesos£¬ËüÃǶ¼ÊÇDockerÉçÇøÖÐ×î¹ã·ºÊ¹ÓõıàÅÅϵͳ£¬Âú×ãÓû§²»Í¬ÌݶȵÄʹÓÃÐÔºÍÌØÐÔ¡£¾¡¹ÜDockerÊǼȶ¨ÊÂʵÉϵÄÐÐÒµÈÝÆ÷±ê×¼£¬µ«ÊÇÔÚÈÝÆ÷±àÅÅÉÏ»¹Ã»Óоø¶ÔµÄÓ®¼Ò¡£ÕâÆªÎÄÕÂÖÐÎÒÃÇÎÒÃÇÖ÷Òª½éÉÜÈýÖÖ±àÅŹ¤¾ßµÄÌØÐÔ£¬ÒÔ¼°ÊÊÓ¦µÄ³¡¾°¡£
ĿǰDockerÔÉú±àÅÅ»¹´¦ÓÚ³õÆÚ½×¶Î£¬µ«ÊÇеÄÌØÐÔÔÚ¿ìËÙµü´úÔö¼ÓÖС£ÓÉÓÚÔÉúµÄ±àÅŹ¤¾ßÊǹٷ½ÏµÍ³µÄÒ»²¿·Ö£¬Òò´ËËü³ÉΪÖڶ࿪·¢ÕßµÄĬÈÏÊ×Ñ¡±àÅŹ¤¾ß£¬Ë³Àí³ÉÕµØ×îÓпÉÄܳÉΪ×îÊÜÉçÇø»¶ÓÖ§³ÖµÄ¹¤¾ß¡£KubernetesÊǹȸèÖ§³ÖµÄÈÝÆ÷±àÅŹ¤¾ß£¬ËüÔÚÖÚ¶àÈÝÆ÷±àÅŹ¤¾ßÖÐÓõÄ×î¹ã·ºµÄÒ»¸ö¡£×î½ü£¬MesosºÍMesosphere£¨MarathonµÄ¿ªÔ´°æ£©°Ñ¸ü¶àµÄ¾«Á¦·ÅÔÚ·þÎñ¹ÜÀí£¬½«¸ü¶àµÄ¹¦ÄÜÁô¸ø¿É²å°Î²å¼þºÍÓ¦ÓóÌÐò¹ÜÀí¡£ÕâÑùµÄ»°£¬¾ÍʹµÃÓ¦ÓÃ×îÖÕÈÝÒ×ÈÝÒ×¶¨ÖƲ¿Êð£¬ÒòΪµ¥¸öµÄ³ÌÐò¸üÈÝÒ×±»¸üУ¬¶¨ÖÆ»¯¡£È»¶ø£¬ÕâÒ²Òâζ×ÅÎÒÃDZØÐëÒªÐÞ¸ÄһЩÉèÖÃÀ´ÊÊÅä¡£Kubernetes¸ü¹Ø×¢µÄÊÇÈçºÎ¹¹½¨¼¯ÈººÍÔÚ³£¼û³¡¾°ÖÐÓÃÀýµÄͨÓÃϵͳ¼¯³É¡£
Docker Native Orchestration

»ù´¡¼Ü¹¹
Docker 1.12ÒýÇæÖи½´øÁËÔÉúµÄ±àÅŹ¤¾ß£¬¶Ô¶ÀÁ¢µÄDocker SwarmÀ´ËµÊÇÒ»ÖÖÌæ´ú¡£Docker±¾µØ¼¯Èº£¨Swarm£©°üºÒ»ÏµÁнڵ㣨Docker½ø³Ì/ÊØ»¤½ø³Ì£©£¬ËûÃÇͬʱ¹ÜÀí¼¯Èº¼°Ìṩ¹¤×÷·þÎñ¡£Äã¿ÉÒÔÔÚÈÝÆ÷ÖÐÆô¶¯¹¤×÷½ø³ÌÒ²¿ÉÒÔÆô¶¯¹ÜÀí½ø³Ìά»¤¼¯ÈºµÄ״̬¡£¶à¹ÜÀíģʽ±£Ö¤ÁËϵͳµÄ¸ß¿ÉÓÃÐÔ£¬µ«ÊDz»ÍƼö³¬¹ý7¸öÒÔÉϹÜÀíÔ±Óû§¡£ÄÚ²¿Í¨¹ýRAFTË㷨ʵÏÖÖ÷´ÓµÄÒ»ÖÂÐÔ¡£ÓëËùÓÐÒ»ÖÂÐÔµÄËã·¨ÊÇÒ»ÑùµÄ£¬¶à¹ÜÀíÖÐÐÄ´ïµ½Ò»ÖÂÐÔµÄʵÏÖ¡£Êµ¼ÊÉϱ£³ÖÄÚ²¿¹ÜÀíµÄÒ»ÖÂÒ²Òâζ×ÅDocker±¾µØµÄ±àÅŲ»ÒÀÀµÍⲿ×ÊÔ´£¬ÕâÑùÒ²ÊǼ¯ÈºµÄ¹ÜÀí±äµÃ¸ü¼ÓÈÝÒס£
¿ÉÓÃÐÔ
Docker±¾»úʹÓõ¥½ÚµãDockerµÄ¸ÅÄ²¢½«ËüÃÇÀ©Õ¹µ½Swarm¡£Èç¹ûÄãʹÓÃ×îеÄDocker°æ±¾£¬ÄÇôѧϰÇúÏß»¹ÊÇÏ൱ƽ»ºµÄ¡£Ò»µ©ÄãÏëÌí¼ÓÒѾÔÚ¶à½ÚµãÔËÐеÄDockerµ½SwarmÖУ¬SwarmµÄÉèÖÃÊǺܼòµ¥µÄ£ºÄãÖ»ÐèÔÚÆäÖÐÒ»¸ö½ÚµãÉϵ÷ÓÃdocker
swarm init£¬È»ºóÔÚÈÎºÎÆäËûÄãÏëÌí¼ÓµÄ½ÚµãÉϵ÷ÓÃdocker swarm join¼´¿É¡£ÄúÒ²¿ÉÒÔʹÓÃÏàͬµÄDocker
ComposeÄ£°åºÍÏàͬµÄDocker CLIÃüÁÉè¼Æµ¥Ò»µÄDocker¡£
¹¦Äܼ¯
Docker±¾µØ¿ÉÒÔʹÓÃÓëDocker EngineºÍDocker ComposeÏàͬµÄÓï·¨Ìṩ±àÅÅÖ§³Ö¡£ÄãÈÔÈ»¿ÉÒÔÁ´½Óµ½·þÎñ£¬´´½¨¾í£¬¶¨Ò忪·ÅµÄ¶Ë¿ÚºÅ¡£ËùÓеÄÕâЩ²Ù×÷¶¼ÊÊÓÃÓÚµ¥¸öµÄ½Úµã£¬³ýÁËÕâЩÐÂÔöÁËÁ½¸öеĸÅÄ·þÎñºÍÍøÂç¡£
Docker·þÎñÊÇÄúµÄ½ÚµãÉÏÆô¶¯µÄÒ»×éÈÝÆ÷£¬²¢ÇÒ±£³ÖÕâЩÅúÁ¿µÄÈÝÆ÷ÔËÐС£Èç¹ûÆäÖÐÒ»¸öÈÝÆ÷Í£Ö¹£¬Ëü½«±»×Ô¶¯Ìæ»»µô¡£ÆäÖзþÎñ·ÖÀàÁ½Àࣺ¸´ÖƺÍÈ«¾Ö¡£¸´ÖÆ·þÎñÔÚ¼¯ÈºÖÐά»¤Ö¸¶¨ÊýÁ¿µÄÈÝÆ÷£¬ÒòΪȫ¾Ö·þÎñÔÚÿ¸ö¼¯Èº½ÚµãÉÏÔËÐÐÒ»¸öʵÀý¡£Òª´´½¨¸´ÖÆ·þÎñ£¬ÇëʹÓÃÏÂÃæµÄÃüÁ
docker service create \ ¨Cname frontend \ ¨Creplicas 5 \ -network my-network \ -p 80:80/tcp nginx:latest. |
ÏÖÔÚ¿ÉÒÔʹÓÃdocker network create ¨Cdriver overlay NETWORK_NAME´´½¨ÃüÃûΪoverlayµÄÍøÂ硣ʹÓÃoverlayÍøÂçÎÒÃÇ¿ÉÒÔ´´½¨Ò»¸ö¹ÂÁ¢¡¢±âƽ¡¢¼ÓÃܵÄÐéÄâÍøÂç»·¾³ÓÃÀ´Æô¶¯ÈÝÆ÷¡£Äã¿ÉÒÔʹÓÃÔ¼ÊøºÍ±êÇ©À´×öһЩ·Ç³£»ù±¾µÄÈÝÆ÷µ÷¶È¡£Ê¹ÓÃÔ¼Êø¿ÉÒÔÏò·þÎñÌí¼Ó¹ØÁª£¬²¢ÇÒËü½«³¢ÊÔ½öÆô¶¯¾ßÓÐÌØÊâ±êÇ©µÄÈÝÆ÷¡£
docker service create \ ¨Cname frontend \ ¨Creplicas 5 \ -network my-network \ --constraint engine.labels.cloud==aws \ --constraint node.role==manager \ -p 80:80/tcp nginx:latest. |
´ËÍ⣬Äã¿ÉÒÔʹÓñ£ÁôµÄCPUºÍ±£ÁôµÄÄÚ´æ¿Õ¼ä±êÖ¾À´¶¨Òå·þÎñµÄÿ¸öÈÝÆ÷ʹÓõÄ×ÊÔ´£¬ÒÔ±ãÔÚswarmÉÏÆô¶¯¶à¸ö·þÎñʱ£¬ÈÝÆ÷¿ÉÒÔ´¦Àí×îСµÄ×ÊÔ´¾ºÕù¡£
Äã¿ÉÒÔʹÓÃÒÔÏÂÃüÁî½øÐгõ²½µÄ²¿Êð¡£ÕâÑù½«»á¸üÐÂÈÝÆ÷µÄ¾µÏñ£¬µ«ÊÇÁ½¸öÈÝÆ÷Ö®¼äÓÐ10sµÄ¼ä¸ôÀ´¸üÐÂÁ½¸öÈÝÆ÷¡£È»¶ø£¬health-checksºÍ×Ô¶¯»Ø¹ö¶¼²»Ö§³Ö¡£
docker service update \ ¨Cname frontend \ ¨Creplicas 5 \ -network my-network \ --update-delay 10s \ --update-parallelism 2 \ -p 80:80/tcp nginx:other-version. |
DockerʹÓþíÇý¶¯³ÌÐòÖ§³ÖÍⲿ¾í³Ö¾Ã»¯£¬²¢ÇÒʹÓÃmount·þÎñÃüÁîÀ©Õ¹Æ÷ʹÓá£Ö´ÐÐÒÔÏ´úÂë¶Î½«»á½«NFS×°Èëµ½ÄúµÄÈÝÆ÷ÖС£Çë×¢Ò⣬ÕâÐèÒªÔÚDockerÍⲿµÄµ×²ãÖ÷»úÉÏÉèÖÃNFS¡£ÔÚûÓÐÖ÷»úÖ§³ÖµÄÇé¿öÏ£¬ÆäËû¶ÔAmazon
EBS¾í»òGoogleÈÝÆ÷ÒýÇæ¾íÇý¶¯³ÌÐòÒ²Äܹ»¹¤×÷¡£´ËÍ⣬Õâ¸ö¹¦ÄÜ»¹Ã»ÓÐÍêÉÆµÄÎĵµ£¬¿ÉÄÜÐèÒªÐèÒªÔÚgithubµÄdockerÏîÄ¿ÉÏ´´½¨issuesµÃµ½½»Á÷»Ø¸´¡£
--mount type=volume,src=/path/on/host,volume-driver=local,\ dst=/path/in/container,volume-opt=type=nfs,\ volume-opt=device=192.168.1.1:/your/nfs/path |

»ù´¡¼Ü¹¹
´Ó¸ÅÄîÉϽ²£¬KubernetesÓеãÀàËÆÓÚSwarm£¬ËüʹÓÃÒ»¸ö´øÓÐRAFTµÄ¹ÜÀíÆ÷£¨Ö÷£©½ÚµãÀ´´ï³ÉÒ»Ö¡£È»¶ø£¬ÏàËÆµÄµØ·½Ò²Ö»ÓÐÕâô¶àÁË¡£KubernetesʹÓÃÍⲿetcd¼¯ÈºÎª´ËÄ¿µÄ¡£´ËÍ⣬Ä㽫ÐèÒªKubernetesÍⲿµÄÍøÂç²ã£¬ÕâÑùoverlay
ÍøÂç¾ÍÐбàÖ¯·¨À¼ÈÞÍâÒÂÒ»Ñù¡£Ê¹ÓÃÕâЩÍⲿ¹¤¾ß£¬Äú¿ÉÒÔÆô¶¯KubernetesÖ÷×é¼þ; API·þÎñÆ÷£¬¿ØÖÆÆ÷¹ÜÀíÆ÷ºÍµ÷¶È³ÌÐò¡£ÕâЩͨ³£×÷ΪÖ÷½ÚµãÉϵÄKubernetes
podÔËÐС£³ýÁËÕâЩ£¬Ä㻹ÐèÒªÔÚÿ¸ö½ÚµãÉÏÔËÐÐkubeletºÍkubeproxy¡£Èç¹ûÐèÒªµÄ»°£¬¹¤×÷½ÚµãÖ»ÔËÐÐKubeletºÍKubeproxyÒÔ¼°ÏñÒ»¸ö°ü×°Ò»Ñù×÷ÎªÍøÂç²ãÌṩÕß¡£
ÔÚÕâ¸öÉèÖÃÖУ¬kubelet½«¿ØÖƸø¶¨½ÚµãÉϵÄÈÝÆ÷£¨»òÕßpod£©ÓëÖ÷¿ØÖÆÆ÷ÉϵĿØÖÆÆ÷¹ÜÀíÆ÷¡£Ö÷½ÚµãÉϵĵ÷¶ÈÆ÷¸ºÔð×ÊÔ´·ÖÅäºÍƽºâ£¬²¢ÇÒ½«°ïÖúÔÚ¾ßÓÐ×î¶à¿ÉÓÃ×ÊÔ´µÄ¹¤×÷½ÚµãÉÏ·ÅÖÃÈÝÆ÷¡£
API¿ØÖÆÆ÷ÊÇÄúµÄ±¾µØkubectl CLI½«Ïò¼¯Èº·¢³öÃüÁîµÄµØ·½¡£×îºó£¬kubeproxyÓÃÓÚΪKubernetesÖж¨ÒåµÄ·þÎñÌṩ¸ºÔØÆ½ºâºÍ¸ß¿ÉÓÃÐÔ¡£

¿ÉÓÃÐÔ
´ÓÍ·¿ªÊ¼ÉèÖÃKubernetesÊÇÒ»¸ö²»Æ½·²µÄŬÁ¦£¬ÒòΪËüÐèÒªÉèÖÃetcd£¬ÍøÂç²å¼þ£¬DNS·þÎñÆ÷ºÍÖ¤Êé°ä·¢»ú¹¹¡£´ÓÍ·¿ªÊ¼ÉèÖÃKubernetesµÄÏêϸÐÅÏ¢¿ÉÒÔÔÚÕâÀµ«ÐÒÔ˵ÄÊÇRancherΪÎÒÃÇÍê³ÉËùÓÐÕâЩÉèÖá£ÎÒÃÇÔÚÇ°ÃæµÄÎÄÕÂÖнéÉÜÁËÈçºÎÉèÖÃKubernetes¼¯Èº¡£
³ýÁ˳õʼÉèÖã¬KubernetesÈÔÈ»ÓÐһЩ¶¸Ç͵ÄѧϰÇúÏߣ¬ÒòΪËüʹÓÃ×Ô¼ºµÄÊõÓïºÍ¸ÅÄî¡£ KubernetesʹÓÃ×ÊÔ´ÀàÐÍ£¬ÈçPods£¬²¿Ê𣬸´ÖÆ¿ØÖÆÆ÷£¬·þÎñ£¬ÊØ»¤½ø³Ì¼¯µÈÀ´¶¨Ò岿Êð¡£ÕâЩ¸ÅÄî²»ÊÇDockerרÃÅ´Ê»ãµÄÒ»²¿·Ö£¬Òò´ËÄúÐèÒªÔÚ¿ªÊ¼´´½¨µÚÒ»¸ö²¿Êð֮ǰÊìϤËüÃÇ¡£´ËÍ⣬һЩÃüÃûÓëDocker³åÍ»¡£ÀýÈ磬Kubernetes·þÎñ²»ÊÇDocker·þÎñ£¬Ò²ÊǸÅÄîÉϲ»Í¬µÄ£¨Docker·þÎñ¸üÌù½üµØÓ³Éäµ½KubernetesÊÀ½çÖеÄDeployments£©¡£´ËÍ⣬ÄúʹÓÃkubectl¶ø²»ÊÇdocker
CLIÓ뼯Ⱥ½»»¥£¬²¢ÇÒ±ØÐëʹÓÃKubernetesÅäÖÃÎļþ¶ø²»ÊÇdocker composeÎļþ¡£
KubernetesÓÐÕâÑùÒ»Ì×ÏêϸµÄ¸ÅÄî¶ÀÁ¢ÓÚcore Docker£¬Õâ±¾Éí²»ÊÇÒ»¼þ»µÊ¡£ KubernetesÌṩ±Ècore
Docker¸ü·á¸»µÄ¹¦Äܼ¯¡£È»¶ø£¬Docker½«Ìí¼Ó¸ü¶àµÄ¹¦ÄÜÀ´ÓëKubernetes¾ºÕù£¬¾ßÓв»Í¬µÄʵÏֺͲ»Í¬»ò³åÍ»µÄ¸ÅÄî¡£Õ⽫¼¸ºõ¿Ï¶¨Öظ´CoreOS
/ rktÇé¿ö£¬´ó²¿·ÖÉçÇøÔÚÀàËÆµ«¾ºÕùµÄ½â¾ö·½°¸¡£½ñÌ죬Docker SwarmºÍKubernetes¶¨Î»ÓÚ²»Í¬µÄʹÓó¡¾°£¨Kubernetes¸üÊʺÏÓÚʹÓÃרÓü¯Èº¹ÜÀíÍŶӵÄÃæÏò·þÎñµÄ¼Ü¹¹µÄ´óÐÍÉú²ú²¿Ê𣩣¬µ«ÊÇËæ×ÅDocker
±¾µØ±àÅŵijÉÊ죬Ëü½«Ç¨ÒƵ½Õâ¸ö¿Õ¼ä¡£
¹¦Äܼ¯
KubernetesµÄÍêÕû¹¦Äܼ¯Ì«´ó£¬ÕâÆªÎÄÕ²»Äܺ¸ÇÍêÕû£¬µ«ÎÒÃǽ«½éÉÜһЩ»ù±¾¸ÅÄîºÍһЩÓÐȤµÄÇø·Ö¡£Ê×ÏÈ£¬KubernetesʹÓÃPodsµÄ¸ÅÄî×÷Ϊ»ù±¾µ¥Î»£¬¶ø²»Êǵ¥¸öÈÝÆ÷¡£Ã¿¸öpodÊÇÒ»×éÈÝÆ÷£¨¼¯ºÏ´óС¿ÉÒÔÊÇÒ»¸ö£©£¬ËüÃÇ×ÜÊÇÔÚͬһ½ÚµãÉÏÆô¶¯£¬¹²ÏíÏàͬµÄ¾í²¢·ÖÅäÒ»¸öÐéÄâIP£¨VIP£©£¬ÒÔ±ã¿ÉÒÔÔÚ¼¯ÈºÖÐѰַ¡£µ¥¸öpodµÄKubernetes¹æ·¶Îļþ¿ÉÄÜÈçÏÂËùʾ£º
kind: Pod metadata: name: mywebservice spec: containers: - name: web-1-10 image: nginx:1.10 ports: - containerPort: 80 |
½ÓÏÂÀ´ÊÇÄãµÄ²¿Êð¡£ÕâЩËÉÉ¢µØÓ³Éä¾ßÌ嵽ʲô·þÎñÊÇÔÚDocker±¾µØ±àÅÅ¡£Äú¿ÉÒÔÏñDocker NativeÖеķþÎñÒ»ÑùÀ©Õ¹²¿Ê𣬲¿Êð½«È·±£ÕýÔÚÔËÐеÄÇëÇóÊýÁ¿µÄÈÝÆ÷¡£ÖØÒªµÄÊÇ×¢ÒⲿÊð½öÀàËÆÓÚDocker±¾µØÖеĸ´ÖÆ·þÎñ£¬ÈçKubernetesʹÓÃÊØ»¤³ÌÐò¼¯¸ÅÄîÀ´Ö§³ÖÆäµÈЧµÄÈ«¾Öµ÷¶È·þÎñ¡£²¿Êð»¹Ö§³ÖʹÓÃHTTP»òTCP¿É´ïÐÔ»ò×Ô¶¨ÒåexecÃüÁîÀ´È·¶¨ÈÝÆ÷/
podÊÇ·ñÕý³£µÄÔËÐÐ×´¿ö¼ì²é¡£²¿Êð»¹Ö§³ÖʹÓÃÔËÐÐ×´¿ö¼ì²éµÄ×Ô¶¯»Ø¹ö¹ö¶¯²¿Êð£¬ÒÔÈ·¶¨Ã¿¸öpod²¿ÊðÊÇ·ñ³É¹¦¡£
kind: Deployment metadata: name: mywebservice-deployment spec: replicas: 2 # We want two pods for this deployment template: metadata: labels: app: mywebservice spec: containers: - name: web-1-10 image: nginx:1.10 ports: - containerPort: 80 |
½ÓÏÂÀ´ÄãÓÐKubernetes·þÎñ£¬ËüΪ²¿ÊðÌṩ¼òµ¥µÄ¸ºÔØÆ½ºâ¡£²¿ÊðÖеÄËùÓÐpod¶¼½«ÔÚ·þÎñ½øÈëºÍÍ˳öʱע²á£¬·þÎñÒ²³éÏó³ö¶à¸ö²¿Êð£¬Òò´ËÈç¹ûÄúÏë»Ø¹ö²¿Êð£¬Äú½«Ê¹ÓÃÏàͬµÄ·þÎñ×¢²áÁ½¸öKubernetes²¿Êð£¬È»ºóÖð¸öÌí¼Ópodͬʱ¼õÉÙpods´ÓÆäËû¡£ÄúÉõÖÁ¿ÉÒÔ½øÐÐblue-green²¿Êð£¬Äú¿ÉÒÔÒ»´ÎÐÔ½«·þÎñÖ¸ÏòеÄKubernetes²¿Êð¡£×îºó£¬·þÎñ¶ÔÓÚKubernetes¼¯ÈºÖеķþÎñ·¢ÏÖÒ²ºÜÓÐÓ㬼¯ÈºÖеÄËùÓзþÎñ¶¼»ñµÃVIP£¬²¢ÇÒ×÷ΪdockerÁ´½ÓÑùʽ»·¾³±äÁ¿ÒÔ¼°Í¨¹ý¼¯³ÉµÄDNS·þÎñÆ÷±©Â¶¸ø¼¯ÈºÖеÄËùÓÐpod¡£
³ýÁË»ù±¾·þÎñ£¬KubernetesÖ§³Ö×÷Òµ£¬µ÷¶È¼Æ»®×÷ÒµºÍPet Sets¡£×÷Òµ´´½¨Ò»¸ö»ò¶à¸öpod£¬²¢µÈ´ýËüÃÇÖÕÖ¹¡£×÷ҵȷ±£Ö¸¶¨ÊýÁ¿µÄpod³É¹¦ÖÕÖ¹¡£ÀýÈ磬Äú¿ÉÒÔ¿ªÊ¼Ò»¸ö×÷Òµ£¬ÔÚ×îºóÒ»Ì쿪ʼ´¦Àí1СʱµÄÉÌÒµÖÇÄÜÊý¾Ý¡£Äú½«Æô¶¯Ò»¸ö°üº¬Ç°Ò»ÌìµÄ24¸öpodµÄ×÷Òµ£¬Ò»µ©ËüÃǶ¼ÔËÐÐÍê³É£¬×÷ÒµÍê³É¡£×÷ΪÃû³Æ½¨ÒéµÄ¼Æ»®×÷ÒµÊÇÔÚ¸ø¶¨¼Æ»®ÉÏ×Ô¶¯ÔËÐеÄ×÷Òµ¡£ÔÚÎÒÃǵÄÀý×ÓÖУ¬ÎÒÃÇ¿ÉÄÜʹÎÒÃǵÄBI´¦ÀíÆ÷ÊÇÿÈռƻ®µÄ¹¤×÷¡£×÷Òµ·Ç³£ÊʺÏÏò¼¯Èº·¢³öÅú´¦Àí¹¤×÷¸ºÔØ£¬ÕâЩ¸ºÔز»×ÜÊÇÐèÒªÆô¶¯µÄ·þÎñ£¬¶øÊÇÐèÒªÔËÐе½Íê³ÉÈ»ºóÇåÀíµÄÈÎÎñ¡£
KubernetesÌṩ¸ø»ù±¾·þÎñµÄÁíÒ»¸öÀ©Õ¹ÊÇPet Sets¡£Pet SetsÖ§³Ö״̬·þÎñ¹¤×÷¸ºÔØ£¬Í¨³£ºÜÄѼ¯Öл¯¡£Õâ°üÀ¨Êý¾Ý¿âºÍʵʱÁ¬½ÓµÄÓ¦ÓóÌÐò¡£Pet
SetsΪ¼¯ºÏÖеÄÿ¸ö¡°Pet¡±ÌṩÎȶ¨µÄÖ÷»úÃû¡£Pet¾ÍÊÇË÷Òý¡£ÀýÈ磬pet5½«¶ÀÁ¢ÓÚpet3¿ÉѰַ£¬²¢ÇÒÈç¹ûµÚÈýPetÈÝÆ÷/
podËÀµô£¬ÔòËü½«ÔÚ¾ßÓÐÏàͬË÷ÒýºÍÖ÷»úÃûµÄÐÂÖ÷»úÉÏÖØÐÂÆô¶¯¡£
Pet Sets»¹ÌṩʹÓó־þíµÄÎȶ¨´æ´¢£¬¼´Èç¹ûpet1ËÀÍö²¢ÔÚÁíÒ»¸ö½ÚµãÉÏÖØÐÂÆô¶¯£¬Ëü½«»ñµÃÆäÖØÐ°²×°ÔʼÊý¾ÝµÄ¾í¡£´ËÍ⣬Äú»¹¿ÉÒÔʹÓÃNFS»òÆäËûÍøÂçÎļþϵͳÔÚÈÝÆ÷Ö®¼ä¹²Ïí¾í£¬¼´Ê¹ËüÃÇÔÚ²»Í¬µÄÖ÷»úÉÏÆô¶¯¡£Õâ½â¾öÁË´Óµ¥Ö÷»úµ½·Ö²¼Ê½Docker»·¾³×ª»»Ê±×îÓÐÎÊÌâµÄÎÊÌâÖ®Ò»¡£
Pet Sets»¹Ìṩ¶ÔµÈ·¢ÏÖ£¬Í¨³£¿ÉÒÔ·¢ÏÖÆäËû·þÎñ£¨Í¨¹ýDockerÁ´½ÓµÈ£©¡£È»¶ø£¬·¢ÏÖ·þÎñÖÐµÄÆäËûÈÝÆ÷ÊDz»¿ÉÄܵġ£ÕâʹµÃÀàËÆCassandraºÍZookeeper»ùÓÚgossipÐÒéµÄ·þÎñ·Ç³£ÄÑÒÔÆô¶¯¡£
×îºó£¬Pet SetsÌṩÆô¶¯ºÍ²ðжÅÅÐò£¬ÕâÊdz־ᢿÉÀ©Õ¹µÄ·þÎñ£¬ÀýÈçCassandra¡£ CassandraÒÀÀµÒ»×éÖÖ×ӽڵ㣬µ±ÄúÉÏÏÂÀ©Õ¹·þÎñʱ£¬±ØÐëÈ·±£ÖÖ×Ó½ÚµãÊǵÚÒ»¸öÆô¶¯µÄ½ÚµãºÍ×îºóÒ»¸öҪɾ³ýµÄ½Úµã¡£ÔÚ׫д±¾ÎÄʱ£¬Pet
SetsÊÇKubernetesµÄÒ»´óÌØÉ«£¬ÒòΪÔÚûÓÐÕâÖÖÖ§³ÖµÄÇé¿öÏ£¬³Ö¾ÃµÄÓÐ״̬¹¤×÷¸ºÔؼ¸ºõ²»¿ÉÄÜÔÚDockerµÄÉú²ú¹æÄ£ÉÏÔËÐС£
Kubernetes»¹ÌṩÃüÃû¿Õ¼äÀ´¸ôÀ뼯ȺÉϵŤ×÷¸ºÔØ£¬±£»¤¹ÜÀíºÍ×Ô¶¯À©Õ¹Ö§³Ö¡£ËùÓÐÕâÐ©ÌØÐÔ¸üÒâζ×ÅKubernetesÒ²Ö§³Ö´óÐÍ£¬¶àÑù»¯µÄ¹¤×÷¸ºÔØ£¬Docker
SwarmĿǰ»¹Ã»ÓÐ×¼±¸¾ÍÐ÷¡£
Marathon

»ù´¡¼Ü¹¹
´ó¹æÄ£¼¯ÈºµÄÁíÒ»¸ö³£¼ûµÄ±àÅÅÉèÖÃÊÇÔÚApache MesosÖ®ÉÏÔËÐÐMarathon¡£ MesosÊÇÒ»¸ö¿ªÔ´¼¯Èº¹ÜÀíϵͳ£¬Ö§³Ö¸÷ÖÖ¹¤×÷¸ºÔØÊý×é¡£
MesosÓÉÔÚȺ¼¯ÖеÄÿ¸öÖ÷»úÉÏÔËÐеÄMesos´úÀí×é³É£¬ËüÏòÖ÷»ú±¨¸æÆä¿ÉÓÃ×ÊÔ´¡£¿ÉÒÔÓÐÒ»¸ö»ò¶à¸öMesosÖ÷»úʹÓÃZooKeeper¼¯Èº½øÐÐе÷¡£ÔÚÈκθø¶¨Ê±¼ä£¬Ö÷½Úµã֮һʹÓÃÖ÷Ñ¡¾Ù¹ý³ÌÊǻµÄ¡£Ö÷·þÎñÆ÷¿ÉÒÔÏòÈκÎMesos´úÀí·¢³öÈÎÎñ£¬²¢±¨¸æÕâЩÈÎÎñµÄ״̬¡£ËäÈ»Äú¿ÉÒÔͨ¹ýAPI·¢³öÈÎÎñ£¬µ«Õý³£µÄ·½·¨ÊÇÔÚMesosÖ®ÉÏʹÓÃÒ»¸ö¿ò¼Ü¡£
MarathonÊÇÒ»¸öÕâÑùµÄ¿ò¼Ü£¬ËüΪÔËÐÐDockerÈÝÆ÷£¨ÒÔ¼°±¾µØMesosÈÝÆ÷£©Ìṩ֧³Ö¡£
¿ÉÓÃÐÔ
ÓëSwarmÏà±È£¬MarathonÓÐÒ»¸öÏ൱¶¸Ç͵ÄѧϰÇúÏߣ¬ÒòΪËü²»ÓëDocker¹²Óô󲿷ָÅÄîºÍÊõÓȻ¶ø£¬ÂíÀËɲ¢²»¸´ÔÓ£¬Òò´Ë±ÈKubernetes¸üÈÝÒ×ѧϰ¡£È»¶ø£¬¹ÜÀíMarathon²¿ÊðµÄ¸´ÔÓÐÔÀ´×ÔÓÚËüÊÇ·Ö²ãÔÚMesos£¬Òò´ËÓÐÁ½²ã¹¤¾ßÒª¹ÜÀí¡£´ËÍ⣬MarathonµÄһЩ¸ü¸ß¼¶¹¦ÄÜ£¨Èç¸ºÔØÆ½ºâ£©½ö×÷ΪÔÚMarathonÖ®ÉÏÔËÐеĸ½¼Ó¿ò¼ÜÌṩ¡£Ä³Ð©¹¦ÄÜ£¨ÈçÉí·ÝÑéÖ¤£©Ö»ÓÐÔÚDC
/ OSÉÏÔËÐÐMarathonʱ²Å¿ÉÓ㬶øºóÕßÓÖÔÚMesosÉÏÔËÐÐ - Ϊ¶ÑÕ»Ìí¼ÓÁíÒ»²ã³éÏó¡£
¹¦Äܼ¯
ÒªÔÚMarathonÖж¨Òå·þÎñ£¬ÄúÐèҪʹÓÃÆäÄÚ²¿JSON¸ñʽ£¬ÈçÏÂËùʾ¡£Ò»¸ö¼òµ¥µÄ¶¨Ò壬ÈçÏÂÃæµÄÒ»¸ö½«´´½¨Ò»¸ö·þÎñ£¬Ã¿¸öÔËÐÐnginxÈÝÆ÷µÄÁ½¸öʵÀý¡£
{ "id": "MyService" "instances": 2, "container": { "type": "DOCKER", "docker": { "network": "BRIDGE", "image": "nginx:latest" } } } |
ÒÔÉ϶¨ÒåÉÔ΢¸üÍêÕûµÄ°æ±¾ÈçÏÂËùʾ£¬ÎÒÃÇÏÖÔÚÌí¼Ó¶Ë¿ÚÓ³ÉäºÍhealth check¡£ÔÚ¶Ë¿ÚÓ³ÉäÖУ¬ÎÒÃÇÖ¸¶¨Ò»¸öÈÝÆ÷¶Ë¿Ú£¬ÕâÊÇdockerÈÝÆ÷¹«¿ªµÄ¶Ë¿Ú¡£Ö÷»ú¶Ë¿Ú¶¨ÒåÖ÷»ú¹«¹²½Ó¿ÚÉϵÄÄĸö¶Ë¿ÚÓ³Éäµ½ÈÝÆ÷¶Ë¿Ú¡£Èç¹ûΪÖ÷»ú¶Ë¿ÚÖ¸¶¨0£¬ÔòÔÚÔËÐÐʱ·ÖÅäËæ»ú¶Ë¿Ú¡£ÀàËÆµØ£¬ÎÒÃÇ¿ÉÒÔ¿ÉÑ¡µØÖ¸¶¨·þÎñ¶Ë¿Ú¡£·þÎñ¶Ë¿ÚÓÃÓÚ·þÎñ·¢Ïֺ͸ºÔØÆ½ºâ£¬Èç±¾½ÚºóÃæËùÊö¡£Ê¹Óý¡¿µ¼ì²é£¬ÎÒÃÇÏÖÔÚ¿ÉÒÔÖ´Ðйö¶¯£¨Ä¬ÈÏ£©ºÍblue-green
²¿Êð¡£
{ "id": "MyService" "instances": 2, "container": { "type": "DOCKER", "docker": { "network": "BRIDGE", "image": "nginx:latest" "portMappings": [ { "containerPort": 8080, "hostPort": 0, "servicePort": 9000, "protocol": "tcp" }, ] } }, "healthChecks": [ { "protocol": "HTTP", "portIndex": 0, "path": "/", "gracePeriodSeconds": 5, "intervalSeconds": 20, "maxConsecutiveFailures": 3 } ] } |
³ýÁ˵¥Ò»·þÎñÖ®Í⣬Äú»¹¿ÉÒÔ¶¨ÒåMarathonÓ¦ÓóÌÐò×飬ʹÓÃǶÌ×Ê÷½á¹¹µÄ·þÎñ¡£ÔÚ×éÖж¨ÒåÓ¦ÓóÌÐòµÄºÃ´¦ÊÇÄܹ»½«Õû¸ö×éËõ·ÅÔÚÒ»Æð¡£ÕâÔÚ΢·þÎñ¶ÑÕ»Öзdz£ÓÐÓã¬ÆäÖе÷Õûµ¥¸ö·þÎñ¿ÉÄÜÊÇÀ§Äѵġ£µ½Ä¿Ç°ÎªÖ¹£¬À©Õ¹¼ÙÉèËùÓзþÎñ½«ÒÔÏàͬµÄËÙÂÊÀ©Õ¹£¬Òò´ËÈç¹ûÄúÐèÒªÒ»¸ö·þÎñµÄ¡°n¡±¸öʵÀý£¬Äú½«»ñµÃËùÓзþÎñµÄ¡°n¡±¸öʵÀý¡£
{ "id": "/product", "groups": [ { "id": "/product/database", "apps": [ { "id": "/product/mongo", ... }, { "id": "/product/mysql", ... } ] },{ "id": "/product/service", "dependencies": ["/product/database"], "apps": [ { "id": "/product/rails-app", ... }, { "id": "/product/play-app", ... } ] } ] } |
³ýÁËÄܹ»¶¨Òå»ù±¾·þÎñÖ®Í⣬Marathon»¹¿ÉÒÔ»ùÓÚÖ¸¶¨Ô¼ÊøÀ´Ö´ÐÐÈÝÆ÷µÄµ÷¶È£¬°üÀ¨Ö¸¶¨·þÎñµÄÿ¸öʵÀý±ØÐëÔÚ²»Í¬µÄÎïÀíÖ÷»ú¡°Ô¼Êø¡±ÉÏ£º[[¡°hostname¡±,
¡°UNIQUE¡±]]¡£Äú¿ÉÒÔʹÓÃcpusºÍmem±ê¼ÇÀ´Ö¸¶¨¸ÃÈÝÆ÷µÄ×ÊÔ´ÀûÓÃÂÊ¡£Ã¿¸öMesos´úÀí±¨¸æÆä×Ü×ÊÔ´¿ÉÓÃÐÔ£¬Òò´Ëµ÷¶È³ÌÐò¿ÉÒÔÒÔÖÇÄÜ·½Ê½ÔÚÖ÷»úÉÏ·ÅÖù¤×÷¸ºÔØ¡£
ĬÈÏÇé¿öÏ£¬MesosÒÀÀµÓÚ´«Í³µÄDocker¶Ë¿ÚÓ³ÉäºÍÍⲿ·þÎñ·¢Ïֺ͸ºÔØÆ½ºâ»úÖÆ¡£µ«ÊÇ£¬×î½üµÄ²âÊÔ¹¦ÄÜÌí¼ÓÁ˶ÔʹÓÃMesos
DNSµÄDNS·þÎñ·¢ÏÖ»òʹÓÃMarathon LBµÄ¸ºÔØÆ½ºâµÄÖ§³Ö¡£ Mesos DNSÊÇÒ»¸öÔÚMesos
LBÖ®ÉÏÔËÐеÄÓ¦ÓóÌÐò£¬Ëü²éѯMesos APIÒÔ»ñÈ¡ËùÓÐÕýÔÚÔËÐеÄÈÎÎñºÍÓ¦ÓóÌÐòµÄÁÐ±í¡£È»ºó£¬ËüΪÔËÐÐÕâЩÈÎÎñµÄ½Úµã´´½¨DNS¼Ç¼¡£È»ºó£¬ËùÓÐMesos´úÀíÊÖ¶¯¸üУ¬ÒÔʹÓÃMesos
DNS·þÎñ×÷ΪÆäÖ÷DNS·þÎñÆ÷¡£ Mesos DNSʹÓÃÓÃÓÚÏòÖ÷»ú×¢²áMesos´úÀíµÄÖ÷»úÃû»òIPµØÖ·;²¢ÇÒ¶Ë¿ÚÓ³Éä¿ÉÒÔ²éѯΪSRV¼Ç¼¡£ÓÉÓÚMarathon
DNSÔÚ´úÀíÖ÷»úÃûÉϹ¤×÷£¬²¢ÇÒÖ÷»úÍøÂç¶Ë¿Ú±ØÐë±»¹«¿ª£¬Òò´Ë²»ÄÜ·¢Éú³åÍ»¡£ Mesos DNSȷʵÌṩÁËÒ»ÖÖ·½·¨À´Îª×´Ì¬¸ºÔسÖÐøÒýÓõ¥¸öÈÝÆ÷£¬ÀýÈçÎÒÃǽ«Äܹ»Ê¹ÓÃKubernetes³èÎO¡£´ËÍ⣬ÓëȺ¼¯ÖÐÈκÎÈÝÆ÷ÉÏ¿ÉѰַKubernetes
VIP²»Í¬£¬ÎÒÃDZØÐëÊÖ¶¯½«/etc/resolve.conf¸üе½Mesos DNS·þÎñÆ÷¼¯£¬²¢ÔÚDNS·þÎñÆ÷¸ü¸Äʱ¸üÐÂÅäÖá£
Marathon-lbʹÓÃÂíÀËÉÈüÊÂ×ÜÏ߸ú×ÙËùÓзþÎñµÄÆô¶¯ºÍ³·Ïú¡£È»ºó£¬ËüÔÚ´úÀí½ÚµãÉÏÆô¶¯HAProxyʵÀý£¬ÒÔ½«Á÷Á¿Öм̵½±ØÐèµÄ·þÎñ½Úµã¡£
Marathon»¹¶Ô³Ö¾ÃÐÔ¾íÒÔ¼°Íⲿ³Ö¾Ã¾íÌṩ²âÊÔÖ§³Ö¡£È»¶ø£¬ÕâÁ½¸öÌØÕ÷¶¼´¦Óڷdz£ÔʼµÄ״̬¡£³Ö¾Ã¾íÖ»ÔÚÈÝÆ÷ÖØÐÂÆô¶¯µÄµ¥¸ö½ÚµãÉϳ־û¯£¬µ«ÊÇÈç¹ûɾ³ýʹÓÃËüÃǵÄÓ¦ÓóÌÐò£¬Ôò»áɾ³ý¾í£¬µ«´ÅÅÌÉϵÄʵ¼ÊÊý¾Ý²»»á±»É¾³ý£¬±ØÐëÊÖ¶¯É¾³ý¡£Íⲿ¾íÐèÒªDC
/ OS£¬²¢ÇÒµ±Ç°Ö»ÔÊÐíÄúµÄ·þÎñÀ©Õ¹µ½µ¥ÊµÀý¡£
×îÖղþö
½ñÌìÎÒÃÇ¿´ÁËDockerÈÝÆ÷±àÅŵÄÈý¸öÑ¡ÏDocker Native£¨Swarm£©£¬KubernetesºÍMesos
/ Marathon¡£ºÜÄÑÑ¡ÔñÒ»¸öϵͳÀ´ÍƼö£¬ÒòΪ×îºÃµÄϵͳ¸ß¶ÈÒÀÀµÓÚÄãµÄÓÃÀý£¬¹æÄ£ºÍÀúÊ·¡£´ËÍ⣬ËùÓÐÈý¸öϵͳ¶¼ÔÚ´óÁ¿¿ª·¢£¬Ò»Ð©º¸ÇµÄ¹¦ÄÜÊDzâÊ԰棬¿ÉÄÜ»áºÜ¿ì¸ü¸Ä£¬É¾³ý»òÌæ»»¡£
Docker Native¸øÄãÌṩÁË×î¿ìµÄÉý¼¶£¬ºÜÉÙÉõÖÁûÓй©Ó¦É̵ķâ±Õ³¬³öÁ˶ÔDockerµÄÒÀÀµ¡£¶ÔDockerµÄÒÀÀµ²»ÊÇÒ»¸ö´óÎÊÌ⣬ÒòΪËüÒѾ³ÉΪÁËʵ¼ÊÉÏÈÝÆ÷±ê×¼¡£¼øÓÚÔÚ±àÅÅÕ½ÕùÖÐȱ·¦Ã÷È·µÄÓ®¼Ò£¬¶øÇÒDocker±¾»úÊÇ×îÁé»îµÄ·½·¨£¬Òò´ËËüÊǼòµ¥µÄweb/statelessÓ¦ÓóÌÐòµÄ²»´íÑ¡Ôñ¡£µ«ÊÇ£¬Docker
NativeĿǰ»¹Ö»ÊÇÒ»¸ö¼Ü×Ó£¬Èç¹ûÄãÐèÒªµÃµ½¸´Ôӵ쬴ó¹æÄ£µÄÓ¦ÓóÌÐòµ½Éú²ú£¬ÄãÐèҪѡÔñÒ»¸öMesos
/ Marathon»òKubernetes¡£
ÔÚMesos / MarathonºÍKubernetesÖ®¼äÒ²²»ÊÇÒ»¸öÈÝÒ×µÄÑ¡Ôñ£¬ÒòΪÁ½Õß¶¼ÓÐ×Ô¼ºµÄÓŵãºÍȱµã¡£
Kubernetes¿Ï¶¨ÊǸü·á¸»ºÍ³ÉÊìµÄÁ½¸ö£¬µ«ËüÒ²ÊÇÒ»¸ö·Ç³£ÓмûµØµÄÈí¼þ¡£ÎÒÃÇÈÏΪºÜ¶àÕâЩÒâ¼ûÊÇÓÐÒâÒåµÄ£¬µ«KubernetesûÓÐÂíÀËɵÄÁé»îÐÔ¡£ÕâÊÇÓеÀÀíµÄ£¬µ±Ä㿼ÂÇ·ÇDocker£¬·ÇÈÝÆ÷»¯µÄÓ¦ÓóÌÐò£¬¿ÉÒÔÔËÐÐÔÚMesos³ýÁËMarathon£¨ÀýÈçHadoop¼¯Èº£©µÄ·á¸»µÄÀúÊ·¡£Èç¹ûÄãÕýÔÚ×öÒ»¸öÂÌÉ«ÁìÓòʵʩ£¬Ò²Ã»ÓÐÇ¿ÁÒµÄÒâ¼û£¬ÈçºÎ²¼¾Ö¼¯Èº£¬»òÄãµÄÒâ¼ûͬÒâ¹È¸è£¬ÄÇôKubernetesÊÇÒ»¸ö¸üºÃµÄÑ¡Ôñ¡£Ïà·´£¬Èç¹ûÄãÓдóµÄ£¬¸´ÔÓµÄÒÅÁô¹¤×÷¸ºÔØ£¬½«Öð½¥×ªÒƵ½ÈÝÆ÷£¬ÄÇôMesos
/ MarathonÊÇÒª×ߵķ¡£
ÁíÒ»¸öÎÊÌâÊǹæÄ££ºKubernetesÒѾ²âÊÔÁËÊýǧ¸ö½Úµã£¬¶øMesosÒѾ²âÊÔÁ˳ÉǧÉÏÍòµÄ½Úµã¡£Èç¹ûÄúÕýÔÚÆô¶¯¾ßÓÐÊýÍò¸ö½ÚµãµÄ¼¯Èº£¬ÔòÐèҪʹÓÃMesosÀ´»ñµÃµ×²ã»ù´¡¼Ü¹¹µÄ¿ÉÀ©Õ¹ÐÔ
- µ«Çë×¢Ò⣬½«¸ß¼¶¹¦ÄÜ£¨ÀýÈç¸ºÔØÆ½ºâ£©À©Õ¹µ½¸Ã·¶Î§ÈÔ½«±£Áô¡£È»¶øÔÚÕâÑùµÄ¹æÄ£Ï£¬³ýÁË×Ðϸµ÷ÕûºÍºï×Ó²¹¶¡£¨Ò»ÖÖÔËÐÐʱ¶¯Ì¬Ìæ»»µÄÈȸüз½·¨£¬±àÕß×¢£©£¬ºÜÉÙÔÙÓÐÏֳɵĽâ¾ö·½°¸Äܹ»Ö±½ÓʹÓá£
UsmanÊÇÒ»Ãû·þÎñÆ÷ºÍ»ù´¡ÉèÊ©¹¤³Ìʦ£¬¾ßÓÐÔÚ¸÷ÖÖÔÆÆ½Ì¨Ö®ÉϹ¹½¨´ó¹æÄ£·Ö²¼Ê½·þÎñµÄ¾Ñé¡£Äã¿ÉÒÔÔÚtechtraits.comÉÏÔĶÁ¸ü¶àËûµÄ¹¤×÷£¬»òÕßÔÚtwitter
@usman_ismail»òÕßGitHubÉϹØ×¢Ëû¡£ |