返回顶部
首页 > 资讯 > 精选 >kubernetes API Server原理分析是怎样的
  • 579
分享到

kubernetes API Server原理分析是怎样的

2023-06-04 17:06:52 579人浏览 泡泡鱼
摘要

这篇文章将为大家详细讲解有关kubernetes api Server原理分析是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一:简介k8s API Server提供了k8s各类资源对

这篇文章将为大家详细讲解有关kubernetes api Server原理分析是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

一:简介
k8s API Server提供了k8s各类资源对象(pod,RC,Service等)的增删改查及watch等Http Rest接口,是整个系统的数据总线和数据中心。功能特性:
1.是集群管理的API入口
2.是资源配额控制的入口
3.提供了完善的集群安全机制
kubernetes API Server原理分析是怎样的

二:概述
通常可以通过命令行工具Kubectl来与API Server交互,它们之间的接口是REST调用,同时也可以使用curl命令行工具进行快速验证。通过配置参数KUBE_MASTER="--master=http://10.116.137.196:8080" 客户获得API Server的访问路径。

1.获取 API的版本信息
curl 10.116.137.196:8080/api

点击(此处)折叠或打开

  1. {

  2.   "kind": "APIVersions",

  3.   "versions": [

  4.     "v1"

  5.   ],

  6.   "serverAddressByClientCIDRs": [

  7.     {

  8.       "clientCIDR": "0.0.0.0/0",

  9.       "serverAddress": "10.116.137.196:6443"

  10.     }

  11.   ]

  12. }

2.获取目前所支持的资源对象的种类
curl 10.116.137.196:8080/api/v1

  1. {

  2.   "kind": "APIResourceList",

  3.   "groupVersion": "v1",

  4.   "resources": [

  5.     {

  6.       "name": "bindings",

  7.       "singularName": "",

  8.       "namespaced": true,

  9.       "kind": "Binding",

  10.       "verbs": [

  11.         "create"

  12.       ]

  13.     },

  14.     {

  15.       "name": "componentstatuses",

  16.       "singularName": "",

  17.       "namespaced": false,

  18.       "kind": "ComponentStatus",

  19.       "verbs": [

  20.         "get",

  21.         "list"

  22.       ],

  23.       "shortNames": [

  24.         "cs"

  25.       ]

  26.     },

  27.     {

  28.       "name": "configmaps",

  29.       "singularName": "",

  30.       "namespaced": true,

  31.       "kind": "ConfigMap",

  32.       "verbs": [

  33.         "create",

  34.         "delete",

  35.         "deletecollection",

  36.         "get",

  37.         "list",

  38.         "patch",

  39.         "update",

  40.         "watch"

  41.       ],

  42.       "shortNames": [

  43.         "cm"

  44.       ]

  45.     },

  46.     {

  47.       "name": "endpoints",

  48.       "singularName": "",

  49.       "namespaced": true,

  50.       "kind": "Endpoints",

  51.       "verbs": [

  52.         "create",

  53.         "delete",

  54.         "deletecollection",

  55.         "get",

  56.         "list",

  57.         "patch",

  58.         "update",

  59.         "watch"

  60.       ],

  61.       "shortNames": [

  62.         "ep"

  63.       ]

  64.     },

  65.     {

  66.       "name": "events",

  67.       "singularName": "",

  68.       "namespaced": true,

  69.       "kind": "Event",

  70.       "verbs": [

  71.         "create",

  72.         "delete",

  73.         "deletecollection",

  74.         "get",

  75.         "list",

  76.         "patch",

  77.         "update",

  78.         "watch"

  79.       ],

  80.       "shortNames": [

  81.         "ev"

  82.       ]

  83.     },

  84.     {

  85.       "name": "limitranges",

  86.       "singularName": "",

  87.       "namespaced": true,

  88.       "kind": "LimitRange",

  89.       "verbs": [

  90.         "create",

  91.         "delete",

  92.         "deletecollection",

  93.         "get",

  94.         "list",

  95.         "patch",

  96.         "update",

  97.         "watch"

  98.       ],

  99.       "shortNames": [

  100.         "limits"

  101.       ]

  102.     },

  103.     {

  104.       "name": "namespaces",

  105.       "singularName": "",

  106.       "namespaced": false,

  107.       "kind": "Namespace",

  108.       "verbs": [

  109.         "create",

  110.         "delete",

  111.         "get",

  112.         "list",

  113.         "patch",

  114.         "update",

  115.         "watch"

  116.       ],

  117.       "shortNames": [

  118.         "ns"

  119.       ]

  120.     },

  121.     {

  122.       "name": "namespaces/finalize",

  123.       "singularName": "",

  124.       "namespaced": false,

  125.       "kind": "Namespace",

  126.       "verbs": [

  127.         "update"

  128.       ]

  129.     },

  130.     {

  131.       "name": "namespaces/status",

  132.       "singularName": "",

  133.       "namespaced": false,

  134.       "kind": "Namespace",

  135.       "verbs": [

  136.         "get",

  137.         "patch",

  138.         "update"

  139.       ]

  140.     },

  141.     {

  142.       "name": "nodes",

  143.       "singularName": "",

  144.       "namespaced": false,

  145.       "kind": "Node",

  146.       "verbs": [

  147.         "create",

  148.         "delete",

  149.         "deletecollection",

  150.         "get",

  151.         "list",

  152.         "patch",

  153.         "proxy",

  154.         "update",

  155.         "watch"

  156.       ],

  157.       "shortNames": [

  158.         "no"

  159.       ]

  160.     },

  161.     {

  162.       "name": "nodes/proxy",

  163.       "singularName": "",

  164.       "namespaced": false,

  165.       "kind": "Node",

  166.       "verbs": []

  167.     },

  168.     {

  169.       "name": "nodes/status",

  170.       "singularName": "",

  171.       "namespaced": false,

  172.       "kind": "Node",

  173.       "verbs": [

  174.         "get",

  175.         "patch",

  176.         "update"

  177.       ]

  178.     },

  179.     {

  180.       "name": "persistentvolumeclaims",

  181.       "singularName": "",

  182.       "namespaced": true,

  183.       "kind": "PersistentVolumeClaim",

  184.       "verbs": [

  185.         "create",

  186.         "delete",

  187.         "deletecollection",

  188.         "get",

  189.         "list",

  190.         "patch",

  191.         "update",

  192.         "watch"

  193.       ],

  194.       "shortNames": [

  195.         "pvc"

  196.       ]

  197.     },

  198.     {

  199.       "name": "persistentvolumeclaims/status",

  200.       "singularName": "",

  201.       "namespaced": true,

  202.       "kind": "PersistentVolumeClaim",

  203.       "verbs": [

  204.         "get",

  205.         "patch",

  206.         "update"

  207.       ]

  208.     },

  209.     {

  210.       "name": "persistentvolumes",

  211.       "singularName": "",

  212.       "namespaced": false,

  213.       "kind": "PersistentVolume",

  214.       "verbs": [

  215.         "create",

  216.         "delete",

  217.         "deletecollection",

  218.         "get",

  219.         "list",

  220.         "patch",

  221.         "update",

  222.         "watch"

  223.       ],

  224.       "shortNames": [

  225.         "pv"

  226.       ]

  227.     },

  228.     {

  229.       "name": "persistentvolumes/status",

  230.       "singularName": "",

  231.       "namespaced": false,

  232.       "kind": "PersistentVolume",

  233.       "verbs": [

  234.         "get",

  235.         "patch",

  236.         "update"

  237.       ]

  238.     },

  239.     {

  240.       "name": "pods",

  241.       "singularName": "",

  242.       "namespaced": true,

  243.       "kind": "Pod",

  244.       "verbs": [

  245.         "create",

  246.         "delete",

  247.         "deletecollection",

  248.         "get",

  249.         "list",

  250.         "patch",

  251.         "proxy",

  252.         "update",

  253.         "watch"

  254.       ],

  255.       "shortNames": [

  256.         "po"

  257.       ],

  258.       "cateGories": [

  259.         "all"

  260.       ]

  261.     },

  262.     {

  263.       "name": "pods/attach",

  264.       "singularName": "",

  265.       "namespaced": true,

  266.       "kind": "Pod",

  267.       "verbs": []

  268.     },

  269.     {

  270.       "name": "pods/binding",

  271.       "singularName": "",

  272.       "namespaced": true,

  273.       "kind": "Binding",

  274.       "verbs": [

  275.         "create"

  276.       ]

  277.     },

  278.     {

  279.       "name": "pods/eviction",

  280.       "singularName": "",

  281.       "namespaced": true,

  282.       "group": "policy",

  283.       "version": "v1beta1",

  284.       "kind": "Eviction",

  285.       "verbs": [

  286.         "create"

  287.       ]

  288.     },

  289.     {

  290.       "name": "pods/exec",

  291.       "singularName": "",

  292.       "namespaced": true,

  293.       "kind": "Pod",

  294.       "verbs": []

  295.     },

  296.     {

  297.       "name": "pods/log",

  298.       "singularName": "",

  299.       "namespaced": true,

  300.       "kind": "Pod",

  301.       "verbs": [

  302.         "get"

  303.       ]

  304.     },

  305.     {

  306.       "name": "pods/portforward",

  307.       "singularName": "",

  308.       "namespaced": true,

  309.       "kind": "Pod",

  310.       "verbs": []

  311.     },

  312.     {

  313.       "name": "pods/proxy",

  314.       "singularName": "",

  315.       "namespaced": true,

  316.       "kind": "Pod",

  317.       "verbs": []

  318.     },

  319.     {

  320.       "name": "pods/status",

  321.       "singularName": "",

  322.       "namespaced": true,

  323.       "kind": "Pod",

  324.       "verbs": [

  325.         "get",

  326.         "patch",

  327.         "update"

  328.       ]

  329.     },

  330.     {

  331.       "name": "podtemplates",

  332.       "singularName": "",

  333.       "namespaced": true,

  334.       "kind": "PodTemplate",

  335.       "verbs": [

  336.         "create",

  337.         "delete",

  338.         "deletecollection",

  339.         "get",

  340.         "list",

  341.         "patch",

  342.         "update",

  343.         "watch"

  344.       ]

  345.     },

  346.     {

  347.       "name": "replicationcontrollers",

  348.       "singularName": "",

  349.       "namespaced": true,

  350.       "kind": "ReplicationController",

  351.       "verbs": [

  352.         "create",

  353.         "delete",

  354.         "deletecollection",

  355.         "get",

  356.         "list",

  357.         "patch",

  358.         "update",

  359.         "watch"

  360.       ],

  361.       "shortNames": [

  362.         "rc"

  363.       ],

  364.       "categories": [

  365.         "all"

  366.       ]

  367.     },

  368.     {

  369.       "name": "replicationcontrollers/scale",

  370.       "singularName": "",

  371.       "namespaced": true,

  372.       "group": "autoscaling",

  373.       "version": "v1",

  374.       "kind": "Scale",

  375.       "verbs": [

  376.         "get",

  377.         "patch",

  378.         "update"

  379.       ]

  380.     },

  381.     {

  382.       "name": "replicationcontrollers/status",

  383.       "singularName": "",

  384.       "namespaced": true,

  385.       "kind": "ReplicationController",

  386.       "verbs": [

  387.         "get",

  388.         "patch",

  389.         "update"

  390.       ]

  391.     },

  392.     {

  393.       "name": "resourcequotas",

  394.       "singularName": "",

  395.       "namespaced": true,

  396.       "kind": "ResourceQuota",

  397.       "verbs": [

  398.         "create",

  399.         "delete",

  400.         "deletecollection",

  401.         "get",

  402.         "list",

  403.         "patch",

  404.         "update",

  405.         "watch"

  406.       ],

  407.       "shortNames": [

  408.         "quota"

  409.       ]

  410.     },

  411.     {

  412.       "name": "resourcequotas/status",

  413.       "singularName": "",

  414.       "namespaced": true,

  415.       "kind": "ResourceQuota",

  416.       "verbs": [

  417.         "get",

  418.         "patch",

  419.         "update"

  420.       ]

  421.     },

  422.     {

  423.       "name": "secrets",

  424.       "singularName": "",

  425.       "namespaced": true,

  426.       "kind": "Secret",

  427.       "verbs": [

  428.         "create",

  429.         "delete",

  430.         "deletecollection",

  431.         "get",

  432.         "list",

  433.         "patch",

  434.         "update",

  435.         "watch"

  436.       ]

  437.     },

  438.     {

  439.       "name": "serviceaccounts",

  440.       "singularName": "",

  441.       "namespaced": true,

  442.       "kind": "ServiceAccount",

  443.       "verbs": [

  444.         "create",

  445.         "delete",

  446.         "deletecollection",

  447.         "get",

  448.         "list",

  449.         "patch",

  450.         "update",

  451.         "watch"

  452.       ],

  453.       "shortNames": [

  454.         "sa"

  455.       ]

  456.     },

  457.     {

  458.       "name": "services",

  459.       "singularName": "",

  460.       "namespaced": true,

  461.       "kind": "Service",

  462.       "verbs": [

  463.         "create",

  464.         "delete",

  465.         "get",

  466.         "list",

  467.         "patch",

  468.         "proxy",

  469.         "update",

  470.         "watch"

  471.       ],

  472.       "shortNames": [

  473.         "svc"

  474.       ],

  475.       "categories": [

  476.         "all"

  477.       ]

  478.     },

  479.     {

  480.       "name": "services/proxy",

  481.       "singularName": "",

  482.       "namespaced": true,

  483.       "kind": "Service",

  484.       "verbs": []

  485.     },

  486.     {

  487.       "name": "services/status",

  488.       "singularName": "",

  489.       "namespaced": true,

  490.       "kind": "Service",

  491.       "verbs": [

  492.         "get",

  493.         "patch",

  494.         "update"

  495.       ]

  496.     }

  497.   ]

  498. }

3.如果只想对外暴露部分REST服务,则可以在Master或其他任何节点上通过运行kubectl proxy进程启动一个内部代理来实现
kubectl proxy --port=8001

三:Kubernetes Proxy API接口

 API Server最主要的REST接口是资源对象的增删改查,另外还有一类特殊的REST接口--Kubernetes  Proxy API接口,这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。

1.Node 相关的接口

点击(此处)折叠或打开

  1. /api/v1/proxy/nodes/{name}/pods/    #列出指定节点内所有Pod的信息

  2. /api/v1/proxy/nodes/{name}/stats/   #列出指定节点内物理资源的统计信息

  3. /api/v1/prxoy/nodes/{name}/spec/    #列出指定节点的概要信息

这里获取的Pod信息来自Node而非etcd数据库,两者时间点可能存在偏差。

2.Pod 相关的接口

点击(此处)折叠或打开

  1. /api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*} #访问pod的某个服务接口

  2. /api/v1/proxy/namespaces/{namespace}/pods/{name} #访问Pod

  3. #以下写法不同,功能一样

  4. /api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*} #访问pod的某个服务接口

  5. /api/v1/namespaces/{namespace}/pods/{name}/proxy               #访问Pod

Pod的proxy接口的作用:在kubernetes集群之外访问某个pod容器的服务(HTTP服务),可以用Proxy API实现,这种场景多用于管理目的,比如逐一排查Service的Pod副本,检查哪些Pod的服务存在异常问题。

3.Service 相关的接口

点击(此处)折叠或打开

  1. /api/v1/proxy/namespaces/{namespace}/services/{name}


四:集群功能模块之间的通信
kubernetes API Server作为集群的核心,负责集群各功能模块之间的通信,集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,通过API Server提供的REST接口(GET\LIST\WATCH方法)来实现,从而实现各模块之间的信息交互。
kubernetes API Server原理分析是怎样的
1. kubelet与API SERVER交互
每个Node节点上的kubelet定期就会调用API Server的REST接口报告自身状态,API Server接收这些信息后,将节点状态信息更新到etcd中。kubelet也通过API Server的Watch接口监听Pod信息,从而对Node机器上的POD进行管理。

2. kube-controller-manager与API SERVER交互
kube-controller-manager中的Node Controller模块通过API Server提供的Watch接口,实时监控Node的信息,并做相应处理。

3.kube-scheduler与API SERVER交互
Scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑。调度成功后将Pod绑定到目标节点上。

五: 说明
为了缓解各模块对API Server的访问压力,各功能模块都采用缓存机制来缓存数据,各功能模块定时从API Server获取指定的资源对象信息(LIST/WATCH方法),然后将信息保存到本地缓存,功能模块在某些情况下不直接访问API Server,而是通过访问缓存数据来间接访问API Server。

关于kubernetes API Server原理分析是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: kubernetes API Server原理分析是怎样的

本文链接: https://lsjlt.com/news/238672.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • kubernetes API Server原理分析是怎样的
    这篇文章将为大家详细讲解有关kubernetes API Server原理分析是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一:简介k8s API Server提供了k8s各类资源对...
    99+
    2023-06-04
  • Kubernetes API server工作原理
    作为Kubernetes的使用者,每天用得最多的命令就是kubectl XXX了。kubectl其实就是一个控制台,主要提供的功能: 提供Kubernetes集群管理的REST API接口,包括认证授权、数据校验以及集群状态变更; 提供其他...
    99+
    2023-06-04
  • Kubernetes Informer的示例分析是怎样的
    Kubernetes Informer的示例分析是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。熟悉Kubernetes的小伙伴们想必会有一窥源码的动机,领略大师的设...
    99+
    2023-06-19
  • 怎样进行Kubernetes的网络原理解析
    这篇文章给大家介绍怎样进行Kubernetes的网络原理解析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. Linux网络基础1.1 名词解释Network Namespace(网络命名空间):Linux...
    99+
    2023-06-04
  • Spring事务的原理分析是怎样的
    这期内容当中小编将会给大家带来有关Spring事务的原理分析是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Spring事务的基本原理Spring事务的本质其实就是...
    99+
    2024-04-02
  • Java泛型的原理分析是怎样的
    这篇文章将为大家详细讲解有关Java泛型的原理分析是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、前言泛型在java中有很重要的地位,在实际开发中用处也很大。二、泛型泛型:是jdk...
    99+
    2023-06-26
  • kubernetes中网络原理的示例分析
    小编给大家分享一下kubernetes中网络原理的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一:体系结构图二:说明1.网络命名空间处于不同命名空间的网...
    99+
    2023-06-04
  • MySQL主从复制的原理分析是怎样的
    这期内容当中小编将会给大家带来有关MySQL主从复制的原理分析是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、基本原理MySQL复制过程分成三步:1)、mast...
    99+
    2024-04-02
  • ThreadLocal原理分析及应用场景是怎样的
    本篇文章给大家分享的是有关ThreadLocal原理分析及应用场景是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. ThreadLocal是什么?有哪些用途?首先介绍...
    99+
    2023-06-22
  • turtle库的安装以及原理分析是怎样的
    这篇文章给大家介绍turtle库的安装以及原理分析是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。turtle库是Python中一个很流行的绘图函数库,主要是依据坐标轴来绘制图像,画笔则是一只小海龟,通过控制海龟...
    99+
    2023-06-02
  • kubernetes中安全机制API Server认证之Service Account Token的示例分析
    这篇文章主要介绍了kubernetes中安全机制API Server认证之Service Account Token的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一...
    99+
    2023-06-04
  • kubernetes原生pipeline的示例分析
    kubernetes原生pipeline的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Tekton Pipeline,是一个k8s native的pipeline, ...
    99+
    2023-06-05
  • kubernetes中云原生的示例分析
    这篇文章主要为大家展示了“kubernetes中云原生的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“kubernetes中云原生的示例分析”这篇文章吧。一: 云原生云原生包含了一组应用...
    99+
    2023-06-04
  • Kubernetes中的网络原理解析该怎么理解
    这篇文章给大家介绍Kubernetes中的网络原理解析该怎么理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。01 覆盖网络覆盖⽹络(overlay network)是将TCP数据包装在另⼀种⽹络包⾥⾯进⾏路由转发和通...
    99+
    2023-06-04
  • kubernetes架构是怎么样的
    小编给大家分享一下kubernetes架构是怎么样的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一:整体架构二:架构模块说明以上是“kubernetes架构是怎...
    99+
    2023-06-04
  • kubernetes中的Scheduler原理是什么
    本篇文章为大家展示了kubernetes中的Scheduler原理是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一: 简介1.Kubernetes  scheduler在整个系统中承...
    99+
    2023-06-04
  • Go defer 原理和源码剖析是怎样的
    本篇文章为大家展示了Go defer 原理和源码剖析是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Go 语言中有一个非常有用的保留字 defer,它可以调用一个函数,该函数的执行被推迟到包裹...
    99+
    2023-06-25
  • SQL server备份和还原机制是怎样的
    这篇文章将为大家详细讲解有关SQL server备份和还原机制是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。  SQL server备份和还原组件为...
    99+
    2024-04-02
  • SQLServer的数据库管理的分析是怎样的
    今天就跟大家聊聊有关SQLServer的数据库管理的分析是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。数据库管理  可以使用SSMS工具来设...
    99+
    2024-04-02
  • Kubernetes scheduler学习笔记是怎样的
    Kubernetes scheduler学习笔记是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。简介Kubernetes是一个强大的编排工具,可以用来很方便的管理许多...
    99+
    2023-06-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作