增删改查

使用kubectl run 来增加一个pod,使用nginx的镜像,开放80端口,副本数为 1

[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/nginx-deploy created

查看

在第一次查看时,因为nginx镜像还需要时间拖拽下来,看到的是还在创建中

也可以使用 -o wide 来查看详细信息

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-7689897d8d-9dh5s 0/1 ContainerCreating 0 6s
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-7689897d8d-9dh5s 0/1 ContainerCreating 0 12s <none> node03.kubernetes <none> <none>

当镜像拖拽完成后,pod就被创建成功了。

[root@master ~]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 1/1 1 1 31s nginx-deploy nginx:1.14-alpine run=nginx-deploy
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-7689897d8d-9dh5s 1/1 Running 0 50s 10.244.1.2 node03.kubernetes <none> <none>

能看到详细信息中,该pod所对应的容器呗创建在node03 上,并且ip地址是:10.244.1.2,目前只能在Kubernetes节点上才能访问,跳过之外是不能访问的。

[root@master ~]# curl 10.244.1.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

service创建

事实上,上述的访问是不可取的,虽然可以访问,但容器的ip可能随时都会被修改或者其他情况导致该ip不可被访问。

此时就需要使用到 service 固定访问端点。使用 kubectl expose 来创建。

使用说明如下:

Usage:
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name]
[--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]

注意: --target-port 表示容器上的端口,--name 表示service的名称,而 --port 表示service暴露的端口

--type=type 类型有: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.

下面开始创建:

[root@master ~]# kubectl expose deployment nginx-deploy --name=nginx --port=80 --target-port=80 --protocol=TCP
service/nginx exposed

查看

[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17h
nginx ClusterIP 10.105.233.197 <none> 80/TCP 6s

测试访问:

这里的访问,直接访问刚刚创建的nginx service所对应的ip

[root@master ~]# curl 10.105.233.197
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

这里需要用到coreDNS,来解析对应的service,这样外部即可访问。要配置coreDNS的域名解析才可。

测试其他pod通过series访问nginx

在master上查看kube-dns 信息

[root@master ~]# kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 17h

创建一个pod,并使用 -it 参数进入到容器中。

[root@master ~]# kubectl run -i -t busybox --image=busybox --restart=Never
If you don't see a command prompt, try pressing enter.
/ #

查看 resolv.conf 文件中DNS

/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5

尝试解析nginx service

/ # nslookup nginx
Server: 10.96.0.10
Address: 10.96.0.10:53 Name: nginx.default.svc.cluster.local
Address: 10.105.233.197 / # nslookup nginx.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53 *** Can't find nginx.default.svc.cluster.local: No answer

可以看到可以解析,尝试访问:

/ # wget -O - -q http://nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

可以直接在busybox中访问 刚刚创建的nginx,没问题。

测试手动变更nginx对应的pod的ip

手动删除一下nginx的pod,这样,ip就会变更,然后在busybox中使用相同的service端点看能否访问。

[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 13m 10.244.2.2 node02.kubernetes <none> <none>
nginx-deploy-7689897d8d-9dh5s 1/1 Running 0 60m 10.244.1.2 node03.kubernetes <none> <none>
[root@master ~]# kubectl delete pod nginx-deploy-7689897d8d-9dh5s
pod "nginx-deploy-7689897d8d-9dh5s" deleted
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 13m 10.244.2.2 node02.kubernetes <none> <none>
nginx-deploy-7689897d8d-lf8p7 1/1 Running 0 13s 10.244.3.2 node01.kubernetes <none> <none>

可以看到,nginx-deploy 的ip已经变更,下面测试访问

/ # wget -O - -q http://nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

依然可以访问。

pod和service之间的关系

查看 nginx 的service 对应的详细信息;

[root@master ~]# kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: run=nginx-deploy
Annotations: <none>
Selector: run=nginx-deploy
Type: ClusterIP
IP: 10.105.233.197
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.3.2:80
Session Affinity: None
Events: <none>

查看pod标签

[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
busybox 1/1 Running 0 30m run=busybox
nginx-deploy-7689897d8d-lf8p7 1/1 Running 0 16m pod-template-hash=7689897d8d,run=nginx-deploy

这里可以看出,因为nginx-deply的pod中,有nginx-deploy标签,而nginx的service的Selector选择的正式nginx-deploy标签,所以会被选中。

这就是pod和service之间的关系

service调度测试

创建一个两个副本的pod

[root@master ~]# kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=2
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/myapp created
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-84cd4b7f95-kzf68 1/1 Running 0 77s 10.244.1.3 node03.kubernetes <none> <none>
myapp-84cd4b7f95-mx5vq 1/1 Running 0 77s 10.244.2.3 node02.kubernetes <none> <none>

在busybox中直接访问myapp

/ # wget -O - -q http://10.244.1.3
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # wget -O - -q http://10.244.1.3/hostname.html
myapp-84cd4b7f95-kzf68
/ # wget -O - -q http://10.244.2.3
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # wget -O - -q http://10.244.2.3/hostname.html
myapp-84cd4b7f95-mx5vq

创建myapp对应的service

[root@master ~]# kubectl expose deployment myapp --name=myapp --port=80
service/myapp exposed
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18h
myapp ClusterIP 10.108.135.202 <none> 80/TCP 4s
nginx ClusterIP 10.96.12.15 <none> 80/TCP 7m41s

在busybox中访问service

/ # wget -O - -q http://myapp
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # wget -O - -q http://myapp/hostname.html
/ # wget -O - -q http://myapp/hostname.html
myapp-84cd4b7f95-mx5vq
/ # wget -O - -q http://myapp/hostname.html
myapp-84cd4b7f95-kzf68

可以看到,当直接访问对应的service的时候,会有一个轮训的效果,这样就起到了负载均衡效果。

动态扩容pod

刚刚创建的myapp是2个副本,这个副本数是可以动态扩容的.

可以使用 kubectl scale 来扩容

Usage:
kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
[options]

操作:

[root@master ~]# kubectl scale --replicas=5 deployment myapp
deployment.extensions/myapp scaled
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 46m
myapp-84cd4b7f95-kzf68 1/1 Running 0 9m56s
myapp-84cd4b7f95-mx5vq 1/1 Running 0 9m56s
myapp-84cd4b7f95-nk8l2 1/1 Running 0 25s
myapp-84cd4b7f95-srlt2 1/1 Running 0 25s
myapp-84cd4b7f95-tgsdd 1/1 Running 0 25s
nginx-deploy-7689897d8d-lf8p7 1/1 Running 0 32m

可以看到已经被调动成功,添加到5个副本数。

同时在看service

/ # while true; do wget -O - -q http://myapp/hostname.html;sleep 1;done
myapp-84cd4b7f95-kzf68
myapp-84cd4b7f95-mx5vq
myapp-84cd4b7f95-tgsdd
myapp-84cd4b7f95-mx5vq
myapp-84cd4b7f95-kzf68
myapp-84cd4b7f95-srlt2
myapp-84cd4b7f95-srlt2
myapp-84cd4b7f95-srlt2
myapp-84cd4b7f95-nk8l2
myapp-84cd4b7f95-mx5vq
myapp-84cd4b7f95-mx5vq
myapp-84cd4b7f95-tgsdd
myapp-84cd4b7f95-nk8l2
myapp-84cd4b7f95-srlt2
myapp-84cd4b7f95-mx5vq
myapp-84cd4b7f95-tgsdd
myapp-84cd4b7f95-kzf68

在service中,已经可以被调度了,并且也是负载均衡效果。

这种添加或者减少,直接操作即可。

滚动升级

可以在线的实现灰度、蓝绿等滚动发布升级。

刚刚创建的myapp是v1版本,下面升级到v2版本,然后查看效果。

使用 kubectl set image 来操作

Usage:
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
[options]

操作:

[root@master ~]# kubectl set image deployment myapp myapp=ikubernetes/myapp:v2
deployment.extensions/myapp image updated
[root@master ~]# kubectl rollout status deployment myapp
Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myapp" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "myapp" rollout to finish: 1 old replicas are pending termination...
deployment "myapp" successfully rolled out

可以使用 kubectl rollout status 来跟踪容器的变化

/ # while true; do wget -O - -q http://myapp;sleep 1;done
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

这里也可以看到访问所带来的变化。

同时,因为版本个更新,所有myapp所有的对应的名称的hash值都变化了,因为都被删除后重新创建的。

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 54m
myapp-746644f8d6-96q2j 1/1 Running 0 2m3s
myapp-746644f8d6-qmqdz 1/1 Running 0 114s
myapp-746644f8d6-xj72g 1/1 Running 0 107s
nginx-deploy-7689897d8d-lf8p7 1/1 Running 0 40m

失败回滚

使用 kubectl rollout 来操作

Usage:
kubectl rollout SUBCOMMAND [options]

操作:

[root@master ~]# kubectl rollout undo deployment myapp
deployment.extensions/myapp rolled back
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 57m
myapp-84cd4b7f95-44qch 1/1 Running 0 54s
myapp-84cd4b7f95-fzvsd 1/1 Running 0 55s
myapp-84cd4b7f95-mlphg 1/1 Running 0 52s
nginx-deploy-7689897d8d-lf8p7 1/1 Running 0 44m

查看访问:

while true; do wget -O - -q http://myapp;sleep 1;done
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

开通集群外访问

上面的所有操作,都仅限于kubernetes集群内部的节点所有资源可以访问。

需要修改service中的类型,来开通访问。

[root@master ~]# kubectl edit svc myapp
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2019-07-10T02:56:26Z"
labels:
run: myapp
name: myapp
namespace: default
resourceVersion: "105517"
selfLink: /api/v1/namespaces/default/services/myapp
uid: 15e48fde-3242-4871-8113-0ae5b91cd634
spec:
clusterIP: 10.108.135.202
externalTrafficPolicy: Cluster
ports:
- nodePort: 31441
port: 80
protocol: TCP
targetPort: 80
selector:
run: myapp
sessionAffinity: None
type: NodePort # 这里修改
status:
loadBalancer: {}

type: ClusterIP 修改为 type: NodePort

然后报错退出,再次查看myapp的service:

[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18h
myapp NodePort 10.108.135.202 <none> 80:31441/TCP 21m
nginx ClusterIP 10.96.12.15 <none> 80/TCP 29m

能看到myapp的port列中, 80: 31441 ,此时kubernetes中所有节点的31441端口都可以被访问到myapp中的nginx容器

找一台kubernetes集群外的机器访问测试:

[root@guanwang ~]# ip a | grep 255
inet 10.0.20.140/24 brd 10.0.20.255 scope global bond0
[root@guanwang ~]# curl 10.0.20.20:31441
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@guanwang ~]# curl 10.0.20.21:31441
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@guanwang ~]# curl 10.0.20.22:31441
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@guanwang ~]# curl 10.0.20.23:31441
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

真实的工作中,极少有机会直接操作上述所有的命令,都会通过ymal格式的配置文件来操作kubernetes中的所有资源。

03-kubernetes 应用快速入门的更多相关文章

  1. 3、kubernetes应用快速入门190625

    一.kubernetes应用入门 1.kubectl命令 Basic Commands create Create a resource from a file or from stdin. expo ...

  2. 超长干货丨Kubernetes网络快速入门完全指南

    Kubernetes网络一直是一个非常复杂的主题.本文将介绍Kubernetes实际如何创建网络以及如何为Kubernetes集群设置网络. 本文不包括如何设置Kubernetes集群.这篇文章中的所 ...

  3. Kubernetes 学习4 kubernetes应用快速入门

    一.相关命令 1.kubectl 通过连接api server 进行各k8s对象资源的增删改查,如pod,service,controller(控制器),我们常用的pod控制器replicaset,d ...

  4. kubernetes 应用快速入门

    使用kubectl进行增.删.查.改等常用操作 查看kubectl命令帮助 kubectl -h kubectl controls the Kubernetes cluster manager. Fi ...

  5. Kubernetes快速入门

    二.Kubernetes快速入门 (1)Kubernetes集群的部署方法及部署要点 (2)部署Kubernetes分布式集群 (3)kubectl使用基础 1.简介 kubectl就是API ser ...

  6. 5分钟带你快速入门和了解 OAM Kubernetes

    什么是 OAM? OAM 的全称为开放应用模型(Open Application Model),由阿里巴巴宣布联合微软共同推出. OAM 解决了什么问题? OAM 本质是为了解耦K8S中现存的形形色色 ...

  7. AngularJS快速入门指南03:表达式

    AngularJS通过表达式将数据绑定到HTML. AngularJS表达式 AngularJS表达式写在双大括号中:{{ 表达式语句 }}. AngularJS表达式绑定数据到HTML的方式与ng- ...

  8. Nginx快速入门菜鸟笔记

    Nginx快速入门-菜鸟笔记   1.编译安装nginx 编译安装nginx 必须先安装pcre库. (1)uname -a 确定环境 Linux localhost.localdomain 2.6. ...

  9. [你必须知道的NOSQL系列]专题二:Redis快速入门

    一.前言 在前一篇博文介绍了MongoDB基本操作,本来打算这篇博文继续介绍MongoDB的相关内容的,例如索引,主从备份等内容的,但是发现这些内容都可以通过官方文档都可以看到,并且都非常详细,所以这 ...

  10. AngularJS快速入门指南04:指令

    AngularJS通过指令将HTML属性进行了扩展. AngularJS指令 AngularJS指令是带有ng-前缀的扩展HTML属性. ng-app指令用来初始化AngularJS applicat ...

随机推荐

  1. Logstash 安装及简单实用(同步MySql数据到Elasticsearch)(Windows)

    Logstash是一款轻量级的日志搜集处理框架,可以方便的把分散的.多样化的日志搜集起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件 Windows环境: 1.下载logstas ...

  2. Web for pentester_writeup之XML attacks篇

    Web for pentester_writeup之XML attacks篇 XML attacks(XML攻击) Example 1 - XML外部实体注入(XXE) Payload http:// ...

  3. Vim 自定义补全利器 Snippet

    Vim Snippet 设置 本人是 vim 用户,可以说能不用 IDE 就不用 IDE. Snippet 是一种支持用户自定义补全的需求,在 vim 中,可以使用 UltiSnips 和 Vim-S ...

  4. 使用websocketpp进行websocket通信

    websocketpp介绍 websocketpp是一个只有头文件的支持websocket协议的C++开源库,支持websocket客户端和服务器功能,网络传输模块基于boost::asio 提供 s ...

  5. PHP 从另一个角度来分析 Laravel 框架的依赖注入功能

    从根本上说,依赖注入不是让对象创建一个依赖关系,也不是让工厂对象去创建对象,而是将所需的依赖变成一个外部对象,使之成为一个"某些人的问题” 你为"某些人的问题”注入了类的依赖关系. ...

  6. 了解Spring的基本概念

    参考资料:https://www.jianshu.com/p/1c483bd8fd6d 在正式学习Spring框架之前,肯定有很多疑问,比如说: 1.Spring中经常出现的IOC.AOP.DI是什么 ...

  7. mui 底部导航栏

    mui 底部导航栏 <nav class="mui-bar mui-bar-tab " id="nav"> <a class="mu ...

  8. nyoj 40-公约数和公倍数(gcd)

    40-公约数和公倍数 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:30 submit:47 题目描述: 小明被一个问题给难住了,现在需要你帮帮忙. ...

  9. 深入理解Kafka必知必会(2)

    Kafka目前有哪些内部topic,它们都有什么特征?各自的作用又是什么? __consumer_offsets:作用是保存 Kafka 消费者的位移信息 __transaction_state:用来 ...

  10. 领扣(LeetCode)删除排序数组中的重复项 个人题解

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 1 ...