体验共享单车

上周日下午14:00,应孩子班主任老师的要求,我到学校开家长会。周末天气不算太热,学校离家的路程也不算远,于是我决定放弃开车,绿色出行^0^。去的时候乘坐的是今年沈城刚刚更换的电动公交车(好像是双动力),回来时,我则第一次体验了共享单车(骑的是摩拜单车)。

共享单车,对于中国一线城市和二线中心城市的人们来说早已不是啥新鲜事物了。共享单车进入沈城的时间相比一线是要晚一些时间的,并且最初只有绿色的酷奇单车一种,直到今年年初ofo摩拜相继开始在这里投放,共享单车出行才逐渐在沈城的年轻人中间流行开来。不过,和一线城市重点地区(比如北京的清华园门口)的单车“车满为患”相比,二线城市的单车投放量还显不足,依旧是供不应求。

一、骑行体验

之所以这么长时间以来一直未体验过共享单车有几方面原因:

  • 上下班路程较长,一直开车;
  • 和孩子一起出去游玩时,共享单车又无法满足我带娃的需求;
  • 最初在沈城投放的酷骑单车样子太丑,实在激发不出来我的骑行愿望^0^;
  • 在北京、上海等单车发达的城市出差或游玩时,因环境陌生,路线不熟悉,单车无法满足。

于是“拖延”至今才有了我的第一次共享单车处女骑。沈城这边摩拜和ofo几乎同时进入,但从可以直接看到、感觉到的情况来看,摩拜的投放量和受欢迎程度似乎要多于ofo,街面上骑行摩拜的数量几乎与具有先发优势的酷骑相当了。我选择了摩拜。这次骑行的总体情况如下图:

img{512x368}

下面简单说说骑行的体验!

关于车:

  • 喜欢ofo的颜色,但却喜欢mobike相对更为小巧的车辆设计以及细节;
  • 开锁还是较快的,10多s吧。中间提示我:把蓝牙打开,会更快,不知为何;
  • 车的制动系统很灵敏,一按就有,这个对于骑车安全非常重要;
  • 车的确很沉,上坡费力。估计和车所使用的金属材质有关,估计也和采用实心的、非充气车胎有关;
  • 车座十分不舒服,骑行一段时间后,就感觉屁股疼;
  • 由于采用了实心胎,所以路感明显,减震变差,路况差之时,颠簸感强烈;
  • 车铃铛的设计非常赞,十分易用,铃声较大,对骑行安全有益。

img{512x368}

关于路:

  • 不骑车不知道,自行车道、行人道被机动车占用严重;
  • 并不是所有路都有自行车道规划,自行车与行人共享道路有安全隐患;
  • 在仅有机动车道的路段,骑自行车是十分危险的;
  • 前一段自行车道与下一段自行车道接驳处的细节处理并不一致:有些地方设计了上下缓坡;有些地方干脆就得骑行者自己上下“台阶”。

关于人:

  • 骑行主力依旧是中青年。经过一次骑行后,发现在大城市的马路上骑行还是有很多风险的,上了年纪的老人(即便身体健康,身体倍棒的)最好不要骑车出行,还是老老实实地坐公交、地铁吧;
  • 用共享单车让孩子学车的也不少,这个真该提醒那些家长:慎重、危险,无保障。尤其是那些让孩子在自行车道甚至是机动车道上学车的家长;
  • 很多人把车一直骑到小区里自己家的单元门门口,其实也无可厚非。但是这样一来在小区外找单车的人由于无法进入小区,而无法骑行,导致资源浪费。尤其是夜间。记得上个月大半夜从火车车站出来,本想找辆单车骑行回家,结果按照GPS上的位置寻找,车都在封闭小区里面(前提是这里投放的单车还很少),害得我白白走了近1km的路,最后还是打车回家的;
  • 大多数人还是非常自觉的。比如:在我们小区门口不干扰行人、车辆正常通行的空闲区且便于取车的地方,就规整地停放着一排单车,这显然是周围居民的自觉行为。即便是放在小区里,也自觉停放在非机动车停车处。

二、骑后感想

共享单车快速发展的这一年多,围绕着共享单车社会上出现了各种“恶意破坏单车事件”,针对这些事件,社会上也出现了各种“照妖镜论”:“国民素质照妖镜”、“人性照妖镜”、“社会照妖镜”等。中国社会正在处于从发展到发达的转型期。国民的素质自然也是处在一个上升期。若非要将当前国民素质平均水平与那些有着几百年资本主义发展史的欧美国家相比,自然还有差距,况且欧美国家国民素质就真的就那么高么?

就共享单车的用户群体而言,绝大多数骑行者都是能自律的,少部分人的低素质行为是难以撼动主流正能量的。

另外,从新生事物发展的角度来看,从“混乱无序”到“合理有序”,再到“优化升级”需要一个过程。移动支付、滴滴出行又有哪个不是如此的呢?和移动支付等类似,共享单车也开始逐渐倒逼政府在规划城市交通基础设施时,切实将单车出行的需求重点考虑进去了,设计和实施合理且安全的自行车车道,甚至是自行车高速路(据说北京已考虑试点)。

中国的共享单车虽然概念来自国外,但中国目前应该走在了世界的前头,是中国又一项可能值得国外友人“羡慕”的生活便利服务(其他两项:高铁、移动支付)。

三、共享单车的前景

共享单车作为一种便民的行业服务刚刚起步,还处于其行业发展的初级阶段。社会已经开始接受并适应拥有共享单车服务的生活了。但随着人们对共享单车概念理解的深入,必将对单车行业提出更进一步的需求:

  • 车的舒适性需进一步改善

现在的单车服务仅是满足了用户解决“最后一公里”问题初步需求,算是“温饱”阶段。就如我上面骑行体验的那样,当前的单车在骑行舒适度方面做得还不够好,还有很大的提升空间。车身重量、座椅舒适度、骑行安全等都将是单车服务公司重点要考虑解决的问题。

  • 骑行者需求细分和差异化

需求细分和差异化是单车发展的必然趋势。就如现在黄金单车、巨无霸单车(宽胎、带变速器)的出现恰是这方面的试水。将来针对不同区域、不同地形地貌、不同区域特色(比如寒冷的东北地区)、不同经济特点区域(比如热门旅游城市)、不同人群必将推出细分的单车服务,以满足差异化的用户群体需求。

  • 车辆投放的进一步合理和均衡

一面“车满为患”,一面“车可罗雀”,一个城区单车实时分布的不均衡导致了此“怪现象”,导致了资源利用率不高。随着单车服务公司在设备和算法方面的逐步改进,通过算法对单车进行进一步的合理分布,并通过实时费用调节机制,让用户“主动”顺应单车的目标规划分布,让单车“合理流动”,达到均衡之势。

  • 与政府的深度合作

在国内,一个行业要想蓬勃壮大,离不开政府的身影。尤其是单车这种公共交通服务,与政府深度合作是必由之路,移动支付、打车软件无不如此。毫不夸张的说,政府垄断了交通规划、设计、实施的所有资源,作为城市交通出行补充手段、绿色典范的共享单车如果能够和政府顺畅合作,以推动提升社会整体交通效率、低碳出行、绿色出行为目标,便可以使得政府手握的资源的有效利用率大幅提升,从而也会给市民们单车出行的带来更好的体验。

四、小结

曾几何时,中国是世界第一的自行车大国,但国人从未因此而骄傲。共享单车的出现一改自行车大国大而不强的局面,使得中国成为了引领世界的绿色出行的典范。共享单车逐渐成为中国城市人民生活中不可或缺的一部分。在可预见的未来,共享单车将与共享汽车(包括无人驾驶的共享电动汽车)、无人公交/地铁等一并成为人们出行的主要方式。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

解决Kubernetes 1.6.4 Dashboard无法访问的问题

前一段时间将之前采用kubeadm安装的Kubernetes 1.5.1环境升级到了1.6.4版本,升级过程较为顺利。由于该k8s cluster是一个测试环境,当时并没有过于关注,就忙别的事情了。最近项目组打算在这个环境下做一些事情,而当我们重新“捡起”这个环境时,发现Kubernetes Dashboard无法访问了。

Kubernetes的dashboard可以有很多种访问方式,比如:可以通过暴露nodeport的方式(无身份验证,不安全)、可以通过访问apiserver的api服务的方式等。我们的Dashboard通过APIServer进行访问:

https://apiserver_ip:secure_port/ui

正常情况下通过浏览器访问:https://apiserver_ip:secure_port/ui,浏览器会弹出身份验证对话框,待输入正确的用户名和密码后,便可成功进入Dashboard了。但当前,我们得到的结果却是:

User "system:anonymous" cannot proxy services in the namespace "kube-system".

而访问apiserver(https://apiserver_ip:secure_port/)得到的结果如下:

User "system:anonymous" cannot get  at the cluster scope.

一、问题原因分析

k8s 1.6.x版本与1.5.x版本的一个很大不同在于1.6.x版本启用了RBACAuthorization mode(授权模型),这点在K8s master init的日志中可以得到证实:

# kubeadm init --apiserver-advertise-address xx.xx.xx
... ...
[init] Using Kubernetes version: v1.6.4
[init] Using Authorization mode: RBAC
[preflight] Running pre-flight checks
[preflight] Starting the kubelet service
[certificates] Generated CA certificate and key.
[certificates] Generated API server certificate and key
.... ...
[apiconfig] Created RBAC rules
[addons] Created essential addon: kube-proxy
[addons] Created essential addon: kube-dns

Your Kubernetes master has initialized successfully!
... ...

《Kubernetes集群的安全配置》一文中我们提到过Kubernetes API server的访问方法:

Authentication(身份验证) -> Authorization(授权)-> Admission Control(入口条件控制)

只不过在Kubernetes 1.5.x及以前的版本中,Authorization的环节都采用了默认的配置,即”AlwaysAllow”,对访问APIServer并不产生什么影响:

# kube-apiserver -h
... ...
--authorization-mode="AlwaysAllow": Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: AlwaysAllow,AlwaysDeny,ABAC,Webhook,RBAC
... ...

但K8s 1.6.x版本中,–authorization-mode的值发生了变化:

# cat /etc/kubernetes/manifests/kube-apiserver.yaml

spec:
  containers:
  - command:
    - kube-apiserver
    - --allow-privileged=true
    ... ...
    - --basic-auth-file=/etc/kubernetes/basic_auth_file
    - --authorization-mode=RBAC
    ... ...

注:这里我们依旧通过basic auth方式进行apiserver的Authentication,而不是用客户端数字证书校验等其他方式。

显然问题的原因就在于这里RBAC授权方式的使用,让我们无法正常访问Dashboard了。

二、Kubernetes RBAC Authorization简介

RBAC Authorization的基本概念是Role和RoleBinding。Role是一些permission的集合;而RoleBinding则是将Role授权给某些User、某些Group或某些ServiceAccount。K8s官方博客《RBAC Support in Kubernetes》一文的中的配图对此做了很生动的诠释:

img{512x368}

从上图中我们可以看到:

Role: pod-reader 拥有Pod的get和list permissions;
RoleBinding: pod-reader 将Role: pod-reader授权给右边的User、Group和ServiceAccount。

和Role和RoleBinding对应的是,K8s还有ClusterRole和ClusterRoleBinding的概念,它们不同之处在于:ClusterRole和ClusterRoleBinding是针对整个Cluster范围内有效的,无论用户或资源所在的namespace是什么;而Role和RoleBinding的作用范围是局限在某个k8s namespace中的。

Kubernetes 1.6.4安装时内建了许多Role/ClusterRole和RoleBinds/ClusterRoleBindings:

# kubectl get role -n kube-system
NAME                                        AGE
extension-apiserver-authentication-reader   50d
system:controller:bootstrap-signer          50d
system:controller:token-cleaner             50d

# kubectl get rolebinding -n kube-system
NAME                                 AGE
system:controller:bootstrap-signer   50d
system:controller:token-cleaner      50d

# kubectl get clusterrole
NAME                                           AGE
admin                                          50d
cluster-admin                                  50d
edit                                           50d
system:auth-delegator                          50d
system:basic-user                              50d
system:controller:attachdetach-controller      50d
... ...
system:discovery                               50d
system:heapster                                50d
system:kube-aggregator                         50d
system:kube-controller-manager                 50d
system:kube-dns                                50d
system:kube-scheduler                          50d
system:node                                    50d
system:node-bootstrapper                       50d
system:node-problem-detector                   50d
system:node-proxier                            50d
system:persistent-volume-provisioner           50d
view                                           50d
weave-net                                      50d

# kubectl get clusterrolebinding
NAME                                           AGE
cluster-admin                                  50d
kubeadm:kubelet-bootstrap                      50d
kubeadm:node-proxier                           50d
kubernetes-dashboard                           50d
system:basic-user                              50d
system:controller:attachdetach-controller      50d
... ...
system:controller:statefulset-controller       50d
system:controller:ttl-controller               50d
system:discovery                               50d
system:kube-controller-manager                 50d
system:kube-dns                                50d
system:kube-scheduler                          50d
system:node                                    50d
system:node-proxier                            50d
weave-net                                      50d

三、Dashboard的role和rolebinding

Kubernetes 1.6.x启用RBAC后,诸多周边插件也都推出了适合K8s 1.6.x的manifest描述文件,比如:weave-net等。Dashboard的manifest文件中也增加了关于rolebinding的描述,我当初用的是1.6.1版本,文件内容摘录如下:

// kubernetes-dashboard.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system
... ...

我们看到在kubernetes-dashboard.yaml中,描述文件新建了一个ClusterRoleBinding:kubernetes-dashboard。该binding将ClusterRole: cluster-admin授权给了一个ServiceAccount: kubernetes-dashboard。我们看看ClusterRole: cluster-admin都包含了哪些permission:

# kubectl get clusterrole/cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: 2017-05-30T14:06:39Z
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "11"
  selfLink: /apis/rbac.authorization.k8s.io/v1beta1/clusterrolescluster-admin
  uid: 331c79dc-4541-11e7-bc9a-12584ec3a8c9
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

可以看到,在rules设定中,cluster-admin似乎拥有了“无限”权限。不过注意:这里仅仅授权给了一个service account,并没有授权给user或group。并且这里的kubernetes-dashboard是dashboard访问apiserver时使用的(下图右侧流程),并不是user访问APIServer时使用的。

img{512x368}

我们需要给登录dashboard或者说apiserver的user(图左侧)进行授权。

四、为user: admin进行授权

我们的kube-apiserver的启动参数中包含:

    - --basic-auth-file=/etc/kubernetes/basic_auth_file

也就是说我们访问apiserver使用的是basic auth的身份验证方式,而user恰为admin。而从本文开头的错误现象来看,admin这个user并未得到足够的授权。这里我们要做的就是给admin选择一个合适的clusterrole。但kubectl并不支持查看user的信息,初始的clusterrolebinding又那么多,一一查看十分麻烦。我们知道cluster-admin这个clusterrole是全权限的,我们就来将admin这个user与clusterrole: cluster-admin bind到一起:

# kubectl create clusterrolebinding login-on-dashboard-with-cluster-admin --clusterrole=cluster-admin --user=admin
clusterrolebinding "login-on-dashboard-with-cluster-admin" created

# kubectl get clusterrolebinding/login-on-dashboard-with-cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: 2017-07-20T08:57:07Z
  name: login-on-dashboard-with-cluster-admin
  resourceVersion: "5363564"
  selfLink: /apis/rbac.authorization.k8s.io/v1beta1/clusterrolebindingslogin-on-dashboard-with-cluster-admin
  uid: 686a3f36-6d29-11e7-8f69-00163e1001d7
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: admin

binding后,我们再来访问一下dashboard UI,不出意外的话,熟悉的dashboard界面就会出现在你的眼前。

注:Kubernetes API Server新增了–anonymous-auth选项,允许匿名请求访问secure port。没有被其他authentication方法拒绝的请求即Anonymous requests, 这样的匿名请求的username为”system:anonymous”, 归属的组为”system:unauthenticated”。并且该选线是默认的。这样一来,当采用chrome浏览器访问dashboard UI时很可能无法弹出用户名、密码输入对话框,导致后续authorization失败。为了保证用户名、密码输入对话框的弹出,需要将–anonymous-auth设置为false:

// /etc/kubernetes/manifests/kube-apiserver.yaml
    - --anonymous-auth=false

用curl测试结果如下:

$curl -u admin:YOUR_PASSWORD -k https://apiserver_ip:secure_port/
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/apps",
    "/apis/apps/v1beta1",
    "/apis/authentication.k8s.io",
    "/apis/authentication.k8s.io/v1",
    "/apis/authentication.k8s.io/v1beta1",
    "/apis/authorization.k8s.io",
    "/apis/authorization.k8s.io/v1",
    "/apis/authorization.k8s.io/v1beta1",
    "/apis/autoscaling",
    "/apis/autoscaling/v1",
    "/apis/autoscaling/v2alpha1",
    "/apis/batch",
    "/apis/batch/v1",
    "/apis/batch/v2alpha1",
    "/apis/certificates.k8s.io",
    "/apis/certificates.k8s.io/v1beta1",
    "/apis/extensions",
    "/apis/extensions/v1beta1",
    "/apis/policy",
    "/apis/policy/v1beta1",
    "/apis/rbac.authorization.k8s.io",
    "/apis/rbac.authorization.k8s.io/v1alpha1",
    "/apis/rbac.authorization.k8s.io/v1beta1",
    "/apis/settings.k8s.io",
    "/apis/settings.k8s.io/v1alpha1",
    "/apis/storage.k8s.io",
    "/apis/storage.k8s.io/v1",
    "/apis/storage.k8s.io/v1beta1",
    "/healthz",
    "/healthz/ping",
    "/healthz/poststarthook/bootstrap-controller",
    "/healthz/poststarthook/ca-registration",
    "/healthz/poststarthook/extensions/third-party-resources",
    "/healthz/poststarthook/rbac/bootstrap-roles",
    "/logs",
    "/metrics",
    "/swaggerapi/",
    "/ui/",
    "/version"
  ]
}


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats