kubernetes 安装 yum install etcd kubernetes vim /etc/sysconfig/docker # OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false' OPTIONS='--selinux-enabled=false --insecure-registry gcr.io --log-driver=journald --signature-verification=false' vim /etc/kubernetes/apiserver # KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota" KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota" vim /etc/kubernetes/apiserver # KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1" KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0" 这个后边api访问要用 一起改了 systemctl start etcd systemctl start docker systemctl start kube-apiserver systemctl start kube-controller-manager systemctl start kube-scheduler systemctl start kubelet systemctl start kube-proxy 搞一个可以执行python的镜像 docker search python docker pull docker.io/python docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/python latest b6cc5d70bc28 3 weeks ago 688.9 MB 测试 docker run -t -i b6cc5d70bc28 /bin/bash 启动输入python, 麻痹 3.6.1的,还好有python2。2.7.9 哈哈 创建个新的镜像,新建Dockerfile # 测试用滴 FROM docker.io/python EXPOSE 8080 # COPY main.py . CMD python2 -m SimpleHTTPServer 8080 docker build -t mytest/pyhttp:v1 . docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytest/pyhttp v1 eefd8b0e5723 About a minute ago 688.9 MB docker.io/python latest b6cc5d70bc28 3 weeks ago 688.9 MB docker run -d eefd8b0e57 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 02e9d5c001c9 eefd8b0e57 "/bin/sh -c 'python2 " 8 seconds ago Up 6 seconds 8080/tcp jovial_shockley docker exec -i -t 02e9d5c001c9 /bin/bash ss -at State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 5 *:http-alt *:* 或者curl 127.0.0.1:8080 没问题了 docker kill 02e9d5c001c9 下边就开始搞k8s了 编辑pyhttp.yaml apiVersion: v1 kind: ReplicationController metadata: name: pyhttp spec: replicas: 2 selector: app: pyhttp template: metadata: labels: app: pyhttp spec: containers: - name: pyhttp image: mytest/pyhttp:v1 ports: - containerPort: 8080 kubectl create -f ./pyhttp.yaml replicationcontroller "pyhttp" created kubectl get rc kubectl get pods NAME READY STATUS RESTARTS AGE pyhttp-26pd2 0/1 ContainerCreating 0 1m pyhttp-v7qk2 0/1 ContainerCreating 0 1m kubectl describe replicationcontrollers/pyhttp kubectl get events 几个看状态的命令,等到都running了,就成功了 docker ps命令看启动了四个容器,两个pyhttp的。两个registry.access.redhat.com/rhel7/pod-infrastructure:latest 再写个httpserver.yaml apiVersion: v1 kind: Service metadata: name: http-service spec: type: NodePort selector: app: pyhttp ports: - protocol: TCP port: 8080 nodePort: 30080 kubectl create -f ./httpserver.yaml kubectl create -f ./httpserver.yaml service "http-service" created [root@localhost code]# kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE http-service 10.254.245.101 8080:30080/TCP 12s kubernetes 10.254.0.1 443/TCP 1h 然后就能通过30080访问了. 不过默认安装防火墙给过滤掉了,从机器外是访问不了的 装了个Dashboard,安装方法从官网github上装的。 我装的k8s是1.5的,安装命令 kubectl create -f https://git.io/kube-dashboard-no-rbac 默认监听的127.0.0.1需要制定地址 kubectl proxy --address='0.0.0.0' 然后就可以了 访问发现是

Unauthorized

看文档好像master上的只能在设置用户名密码的时候才能用 kubectl proxy --address='0.0.0.0' --accept-hosts='^*$' 然后跳转变成503. status: "Failure", message: "no endpoints available for service "kubernetes-dashboard"", reason: "ServiceUnavailable", 发现后端启动不成功 [root@localhost ~]# kubectl get pods --namespace=kube-system NAME READY STATUS RESTARTS AGE kubernetes-dashboard-3585514280-q29ml 0/1 CrashLoopBackOff 2 43s [root@localhost ~]# kubectl logs kubernetes-dashboard-3585514280-q29ml -n kube-system Using HTTP port: 8443 Error while initializing connection to Kubernetes apiserver. This most likely means that the cluster is misconfigured (e.g., it has invalid apiserver certificates or service accounts configuration) or the --apiserver-host param points to a server that does not exist. Reason: open /var/run/secrets/kubernetes.io/serviceaccount/token: no such file or directory Refer to the troubleshooting guide for more information: https://github.com/kubernetes/dashboard/blob/master/docs/user-guide/troubleshooting.md 然后搜索有人说要把yaml指定,发现里边确实有注释,默认不行就指定。 - --apiserver-host=http://10.254.0.1:80 这个apiserver ip 命令 kubectl describe svc kubernetes 获取 然后发现还是不行,会出现timeout,这次能running了但是一会儿还是503 但是配置成http://192.168.49.111:8080的api访问地址就行了,外网也能访问了。具体还不太了解原理

Continue

使用pkg命令的时候报错 pkg: warning: database version 34 is newer than libpkg(3) version 33, but still compatible pkg: sqlite error while executing INSERT OR ROLLBACK INTO pkg_search(id, name, origin) VALUES (?1, ?2 || '-' || ?3, ?4); in file pkgdb.c:1544: no such table: pkg_search 从网上找到解决办法 pkg shell sqlite> CREATE VIRTUAL TABLE pkg_search USING fts4(id, name, origin); sqlite> sqlite> pragma user_version=33; 然后使用pkg lock pkg 锁定pkg版本,就不会要你升级pkg版本了

Continue

之前一直放在sae上,用的wordpress。最近sae收费了,而且还死贵,不划算,准备放到阿里云上的主机上,这样还不用花钱了。 用flask重写了,数据库没设计,直接用的wordpress的,界面还是用的之前的。把没用的js啥的去掉了。 写的很匆忙,因为想着能用就行了,先迁移过去,后边慢慢加功能。现在评论添加功能都没实现。先这样吧。

Continue

开始只在在线Clojure网站上进行一些测试,后来感觉不行,操作速度都太慢。决定还是安装个环境。 去clojure官网看了一下也不麻烦。 去官网下载个zip包,解压到目录。 进入目录创建一个bin目录,新建一个clojure文件.添加几行代码

if [ x$* != x ]
then
    java -cp /Users/a0x55aa/tools/clojure-1.8.0/clojure-1.8.0.jar clojure.main "$*"
else
    java -cp /Users/a0x55aa/tools/clojure-1.8.0/clojure-1.8.0.jar clojure.main
fi
然后加入环境变量path种就行了,方便到处使用.

Continue

接上次看的往下看 cli.Pidfile 创建pid文件"/var/run/docker.pid" serverConfig := &apiserver.Config{ Logging: true, SocketGroup: cli.Config.SocketGroup, Version: dockerversion.Version, EnableCors: cli.Config.EnableCors, CorsHeaders: cli.Config.CorsHeaders, } 这几个默认值为 SocketGroup 为docker, EnableCors false, CorsHeaders 这个看EnableCors api := apiserver.New(serverConfig) 这个就是实例化了个Server,cfg为上边的serverConfig cli.api = api 返回一个, 初始化cfg为serverConfig,看起来所有请求的路由都在这里了 type Server struct { cfg *Config servers []*HTTPServer routers []router.Router routerSwapper *routerSwapper middlewares []middleware.Middleware } cli.Config.Hosts没有的话创建一个长度1的数组,有的话进入循环进行监听 listeners.Init wrapListeners(proto, ls) allocateDaemonPort(addr) api.Accept(addr, ls...) 监听地址, 根据hosts初始化的多个httpserver。 migrateKey 这个看起来好像是为了升级还是啥的。把之前配置文件目录的key.json移动到/etc/docker/下边,并把旧的删除 具体不知道为啥这么做 registryService := registry.NewService(cli.Config.ServiceOptions) 返回一个DefaultService newServiceConfig(options)里边,配置镜像仓库地址 containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...) 重头戏来了, getLibcontainerdRoot /var/run/docker/libcontainerd getPlatformRemoteOptions 里边好像就是设置了一些参数 libcontainerd.WithRemoteAddr 这个是设置了ContainerdAddr配置,containerd参数走这个,调用rpcAddr(addr)。 没设置 走libcontainerd.WithStartDaemon(true), 然后调用startDaemon(start) type RemoteOption interface { Apply(Remote) error } New里边先初始化remote eventTsPath getLibcontainerdRoot/event.ts option.Apply(r)这里应该就是真正设置参数到初始化的remote了。不知道为啥这么写 创建getLibcontainerdRoot也就是stateDir 700权限 如果没有rpcAddr 设置 stateDir/docker-containerd.sock startDaemon默认是true的所以肯定执行r.runContainerdDaemon() runContainerdDaemon里 pidFilename stateDir/docker-containerd.pid,下面判断pid文件是否正确,如果进程在运行赋值r.daemonPid,就返回结束了 如果没运行,先设置运行参数,然后执行命令启动docker-containerd setOOMScore oomScoreAdjPath := fmt.Sprintf("/proc/%d/oom_score_adj", pid) 好像就把参数那个数写文件里了,默认-500 写进程号 建了一个r.daemonWaitCh channel,container进程结束后,关闭这个channel。赋值r.daemonPid 总的来说就是启动container进程 使用grpc创建rpc连接 r.rpcConn = conn r.apiClient = containerd.NewAPIClient(conn) 返回 type aPIClient struct { cc *grpc.ClientConn } 就保存了rpc连接 getLastEventTimestamp就是看 stateDir/event.ts 文件,没数据就返回当前时间,如果有,里边保存的是序列号化的,反序列化一下返回 tsp, err := ptypes.TimestampProto(t)转了一下时间 r.restoreFromTimestamp = tsp go r.handleConnectionChange() 大体看了一下,就是开个协程进行rpc连接探测, 连续失败到三次,如果进程存在kill.<-r.daemonWaitCh,然后r.runContainerdDaemon()启动 r.startEventsMonitor(); 监控请求事件 发送了一个"/types.API/Events"请求, 然后开个协程有事件就处理事件 处理完更新事件时间 处理事件这里先不仔细看了。感觉看下去脑子回不来了. libcontainerd/remote_unix.go startEventsMonitor()标记一下,以后看 主要就是server的启动和containerd的启动

Continue

编辑freebsd文件~/.cshrc setenv LANG zh_CN.UTF-8 setenv LC_CTYPE zh_CN.UTF-8 setenv LC_ALL zh_CN.UTF-8 就可以显示中文了。 这里碰到了一点问题,突然发现ssh登录不上,登录的时候得ctrl c 才能显示命令提示符。不知道啥问题,时间长了就说远程断开连接。然后登录一个shell,再登录一个shell,观察发现,ssh,csh进程内存疯长,ulimit datasize相对于虚拟机大多了。直接把swap爆掉了就。爆了一个"kernel: swap_pager_getswapspace(16): failed"的错误。查了一大顿发现好像没人碰到过这个问题。然后就找工具调试,发现自带的有个truss,就试了一下。 发现全是在进行read(6,"\M^B",1)内核调用。然后从头大体看了一下,各种读的前边是跟语言相关的东西。然后找目录还是啥的报了各种找不到,猜测是不是这里有问题。其实啥没看懂,,只能懵逼。 我之前是在~/.login里配置的中文,现在挪到.cshrc里边。就好了。好奇怪的问题。。

Continue

rootkit hunter能检查一下系统是否被安装后门,听说很厉害。 去官网下载一个tar包,解压 安装 ./installer.sh --layout custom /opt/temp/rkhunter --install 这个是指定安装目录,日志都会打到/var/log/rkhunter.log 更新rootkit hunter的数据库 /opt/temp/rkhunter/bin/rkhunter --update 进行检查 /opt/temp/rkhunter/bin/rkhunter --checkall 然后查看结果 cat /var/log/rkhunter.log|grep "Warning\|Vulnerable" cat /var/log/rkhunter.log|grep -A 30 "System checks summary" 这个关键字可能不准确,具体看看总结,再细看检查的过程。

Continue

在用Grafana绘图,后端时序数据库用的InfluxDB。在进行绘图的时候用到取top n的数据。有一个top函数,但是里边不能有函数计算了。我是先group by tag 然后求和的。 查了好多看大部分都是top,开始搜的时候还搜的Grafana,后来想到这是influxdb的查询。找到官方文档,有一个limit和slimit. 这里是有区别的,slimit是相当于之前想法的limit,只去分组的top n。而limit是取每个分组下的top n。 但是order by 也不能 用聚合的字段来,还不知道排序怎么搞。 感觉influxdb还是很新的东西,好多东西太难搞了。也许是不了解。。

Continue

dockerd/daemon.go start() loadDaemonCliConfig(opts) 里 daemon.MergeDaemonConfigurations(config, flags, opts.configFile)将配置文件设置的参数和命令参数合并。 过了好多代码,感觉都是配置啥的就不看具体干啥了。 setDefaultUmask() 设置umask 0022,把goup和other的写权限干掉了。 daemon.CreateDaemonRoot(cli.Config) 先获取docker daemon根目录 默认/var/lib/docker setupRemappedRoot 根据配置映射容器用户和组的 这个参数默认是空的,也就是不映射 如果设置了这个参数 parseRemappedRoot就是解析参数的,有四种格式 username username:groupname uid uid:gid 然后解析/etc/passwd和/etc/group看看参数对不对。其中解析是否是defaultIDSpecifier 就是个'default',然后映射的host用户为dockremap。 也就是RemappedRoot这个参数传个default就行了,使用docker创建好的账户 idtools.AddNamespaceRangesUser(defaultRemappedID)就是判断是否有default的用户,没有就创建 uidMaps, gidMaps, err = idtools.CreateIDMappings(username, groupname) 这个从/etc/subuid和/etc/subgid获取,根据username判断是第一个 startid是uid是第二个,length还不知道干啥的第三个 ALL不知道干啥的 返回了所有的行,就是所有用户 createIDMap返回IDMap,ContainerID开始是0然后后边的都加length。hostid,就是第二个startid, size 是length. 然后setupRemappedRoot就完了,返回了俩idmap idtools.GetRootUIDGID(uidMaps, gidMaps) 里边就一个ToHost(0, uidMap)这个单个的时候就是返回之前的hostid就是startid对应host上的uid, 之前的ALL的话,好像还是只返回了第一个的hostid setupDaemonRoot(config, realRoot, rootUID, rootGID) 修改docker的根目录权限为711 RemappedRoot 为空就直接返回了。不空的话创建一个config.Root目录在docker根目录下。目录名为rootUID.rootGID,权限700.然后好像判断目录下的rootUID都有访问权限,这个应该是为已经有这个目录的判断 然后CreateDaemonRoot完结撒花,设置了一下目录,用户的映射

Continue

东西太多了,大体过了一下,感觉会少了很多东西。有一些三方库,也没去看库怎么用。就看函数名大体猜一下功能。 完全就是从main函数一步一步往下看,这种看法就是缺少一个大局的认识,开始会有很多不理解的做法。 cmd/dockerd/docker.go reexec.Init() 必须要提前调用的方法,用来初始化。如果初始化过了就会返回true,main函数也退出了。 判断是否调用过,就是看看registeredInitializers里有没有os.Args[0]的key。 如果有调用value,没有直接返回false,接着走main函数 具体value是个啥函数,慢慢看.里边还有个Register(函数用来往registeredInitializers里添加值。 cmd := newDaemonCommand() cmd.Execute() 这里一看就跟client的结构一样,突然就感觉好看多了。。 daemonOptions daemon.NewConfig() 返回一个Config,所有配置应该都在这,太多了,也看不到啥意思先过了。 cliflags.NewCommonOptions() 对应client TLS相关的东西,这里一样。 其他都一样。 opts.daemonConfig.InstallFlags(flags) 定义都有哪些参数,太多不看,在help命令里应该是有的。配置了对应的Config里边的字段。 看看return runDaemon(opts) daemonCli := NewDaemonCli() 返回一个DaemonCli type DaemonCli struct { *daemon.Config configFile *string flags *pflag.FlagSet api *apiserver.Server d *daemon.Daemon authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins } err = daemonCli.start(opts) 这里流程就完了。详细看看start是干嘛的

Continue