dashboard开发环境搭建

1.dashboard开发环境搭建(Linux -ubuntu 16.04.2)

参考:dashboard工程目录/docs/devel下的requirements-installation.md和getting-started.mdcss

unbuntu安装 & java7安装

1)ubuntu 16.04.2 下载

地址:http://mirror.bjtu.edu.cn/ubuntu-releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso 虚拟机安装。html

安装后升级linux(可选)前端

sudo apt-get update		
sudo apt-get upgrade

其中:
update 是同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,这样才能获取到最新的软件包。
upgrade 是升级已安装的全部软件包,升级以后的版本就是本地索引里的,所以,在执行 upgrade 以前必定要执行 update, 这样才能是最新的。java

ubutun 版本验证命令:uname -rlsb_release -anode

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial

后续命令操做都切换到root下执行su rootpython

2)网络设置

使用图形化界面修改,系统设置/硬件/网络/有线/选项/iov4设置.....linux

3)java(7+)下载安装:

Ubuntu16.04的安装源已经默认没有openjdk7了,因此要本身手动添加仓库,以下:webpack

add-apt-repository ppa:openjdk-r/ppa   
apt-get update   
apt-get install openjdk-7-jdk
java -version

4) 其余相关下载

apt-get install curl   
apt-get install git
apt-get install openssh-server

其中:
curl 后续ubuntu下载东西须要用到,版本验证curl --version
git 以后从github上check出dashboard代码,版本验证git --version
openssh-server 使用ssh远程ubuntugit

Docker(1.10+)安装&配置

1)升级source列表并保证https和ca证书成功安装es6

apt-get update
apt-get install apt-transport-https ca-certificates

2)增长新的GPG 密钥

apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

3)建立source列表里的docker.list

$ sudo bash -c 'echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" > /etc/apt/sources.list.d/docker.list'

4)安装docker

apt-get install docker.io	#安装docker
service docker start		#启动docker
service docker status		#docker是否启动
docker info			#docker基本信息,包括版本
docker run hello-world		#验证docker是否可用

5)docker配置

groupadd docker
usermod -aG docker root

6)中国官方镜像加速
修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值。

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

修改保存后重启 Docker 以使配置生效service docker restart

go(1.7+)安装&环境配置&IDE

下载go1.8

wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.8.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.profile
echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile

验证

go version
echo $PATH

IDE使用:JetBrains Gogland

前端环境搭建:nodejs(5.1.1+),npm(3+),gulp(3.9+)

nodejs和npm 下载&验证:

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
apt-get install -y nodejs	
node -v	 
npm -v

Gulp下载&验证

npm install --global gulp-cli
npm install --global gulp
gulp -v

npm镜像

npm install cnpm -g --registry=https://registry.npm.taobao.org

cnpm跟npm用法彻底一致,只是在执行命令时将npm改成cnpm

工程项目概况

从github上下载dashboard源码:git clone https://github.com/kubernetes/dashboard.git

前端:SPA, ES6/babel, Angular1.6, gulp, bower,karma, BrowerSync 后端:Go

构建

开发环境执行

npm install 设置环境变量KUBE_DASHBOARD_APISERVER_HOST为k8s的api server的ip端口。 执行gulp serve ,可访问http://localhost:9090

BrowserSync (9090) ---> Dashboard backend (9091) ---> Kubernetes API server (8080)

生产环节

编译代码执行gulp build:编译,压缩前台代码,编译后台代码到dist目录。
执行gulp serve:prod,可访问http://localhost:9090

Dashboard backend (9090) ---> Kubernetes API server (8080)

打包成docker镜像执行:gulp docker-image:canary

配置文件.babelrc

Babel的配置文件,该文件用来设置转码规则和插件,设置ES6

{
  "presets": ["es2015"]
}

相关预备知识

gulp

BrowerSync

Go

ES5 & ES6

ES5:严格模式,JSON,添加对象,额外的数组,Function.prototype.bind
ES6:let&const, 解构,箭头函数,默认参数,rest&spread,字符串模板,集合类型,模块,Promise,Class,Iterators, Generators, Proxies&Reflecion, Symbols....

Angular1.x

MVVM:视图 - 模型 - 视图模型

2.dashboard开发环境搭建(windows)

  • Docker (1.10+)
  • go (1.7+)
  • nodejs (5.1.1+)
  • npm (3+)
  • java (7+)
  • gulp (3.9+)

npm 配置

npm config set prefix "D:\node\node-global"<!--配置全局安装目录-->
npm config set cache "D:\node\node-cache"<!--配置缓存目录-->
配置环境变量NODE_PATH   设置为node_modules的文件夹路径  D:\node\node-global\node_modules 
npm config set registry https://registry.npm.taobao.org

安装python2.7

安装vs expression 2013 for desk(VS2013_RTM_DskExp_CHS.iso)

npm config set python C:\Python27\python.exe  
npm config set msvs_version 2013 --global  
npm install

再在gitbash里手动执行build/postinstall.sh

go包管理

go get -u github.com/kardianos/govendor Warning: 须要把 $GOPATH/bin/ 加到 PATH 中。 http://www.javashuo.com/article/p-anloqoxq-gq.html

跨平台

1)const sourceGopath = ${conf.paths.backendTmp}${path.delimiter}${conf.paths.backendVendor}; 路径分隔符,文件分隔符
2)gocommad.js里的which命令改为where
3)java -Dfile.encoding=utf-8 i18n下文件的编码问题
-jar F:\WORK\work_go\src\github.com\kubernetes\dashboard.tools\xtbgenerator\bin\XtbGenerator.jar --lang en --xtb_output_file F:\WORK\work_go\src\github.com\kubernetes\dashboard\i18n\messages-en.xtb --js F:\WORK\work_go\src\github.com\kubernetes\dashboard.tmp\serve*.js --js F:\WORK\work_go\src\github.com\kubernetes\dashboard.tmp\messages_for_extraction*.js --translations_file F:\WORK\work_go\src\github.com\kubernetes\dashboard\i18n\messages-en.xtb MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 3 无

4)18n

let command = `java -Dfile.encoding=utf-8 -jar ${conf.paths.xtbgenerator} --lang ${langKey}` +
  
//let messageVarPrefix = filePath.toUpperCase().split('/').join('_').replace('.HTML', '');
  let messageVarPrefix = filePath.toUpperCase().replace(/\\/g,"\/").split('/').join('_').replace('.HTML', '');
  
/*
* gulp-google-closure-compiler: deploy/helpsection/userhelp.html.js:5: ERROR - Parse error. Hex digit expected
 $templateCache.put('deploy\helpsection\userhelp.html', ' <div ng-transclude class="kd-user-help" layout-align="start center"> </div> ');
 报错信息说是发现非法16进制数据,这个问题很是蹊跷,也是windows平台和linux平台的路径分隔符不一致所致,是上面的\userhelp.html形成的,由于\u在js中表明后面接着的是16进制数,打开build/i18n.js,将:
 * */
file.moduleContent = `` +
    `import module from 'index_module';\n\n${file.messages}\n` +
    `module.run(['$templateCache', ($templateCache) => {\n` +
    `    $templateCache.put('${filePath.replace(/\\/g,"\\\\")}', '${content}');\n` +
    `}]);\n`;

5)gocommand.js

import path from 'path';
const sourceGopath = `${conf.paths.backendTmp}${path.delimiter}${conf.paths.backendVendor}`;
// Add the project's required go tools to the PATH.
const devPath = `${process.env.PATH}${path.delimiter}${conf.paths.goTools}/bin`;

6)build.js

let searchPath = [
// To resolve local paths.
path.relative(conf.paths.base, conf.paths.prodTmp),
// To resolve bower_components/... paths.
path.relative(conf.paths.base, conf.paths.base)+'/',
  ];

7)package.json

"babel-core": "~6.24.0",
"babel-loader": "~7.0.0",
"babel-preset-es2015": "~6.24.0",

babel版本问题,1.6.3里的版本有问题会报错

8)dashboard ENONE 第一次使用exe结尾,之后不用exe结尾也能够启动

9)minikube本地安装
kubectl config view 获取kubeconfig
证书访问https

--insecure-port=9091
--apiserver-host=https://192.168.0.9:8443
--kubeconfig=F:\temp\kubeconfig

安装minikube https://kubernetes.io/docs/getting-started-guides/minikube/

备忘

"D:\Program_Files\JetBrains\Gogland 171.4694.61\bin\runnerw.exe" D:\Program_Files\nodejs\node.exe F:\WORK\work_go\src\github.com\kubernetes\dashboard\node_modules\gulp\bin\gulp.js --color --gulpfile F:\WORK\work_go\src\github.com\kubernetes\dashboard\gulpfile.babel.js serve-nospawn-backend
[16:49:00] Requiring external module babel-register
[16:50:03] Using gulpfile F:\WORK\work_go\src\github.com\kubernetes\dashboard\gulpfile.babel.js
[16:50:03] Starting 'scripts'...
[16:50:07] Starting 'styles'...
[16:50:07] Starting 'buildExistingI18nCache'...
[16:50:12] Finished 'buildExistingI18nCache' after 4.21 s
[16:50:12] Starting 'angular-templates'...
[16:50:26] Finished 'scripts' after 23 s
[16:50:27] Finished 'styles' after 19 s
[16:50:27] Starting 'index'...
[16:50:27] Finished 'index' after 385 ms
[16:50:28] Finished 'angular-templates' after 17 s
[16:50:28] Starting 'watch-nobackend'...
[16:50:29] Finished 'watch-nobackend' after 702 ms
[16:50:29] Starting 'serve-nospawn-backend'...
[HPM] Proxy created: /api  ->  http://localhost:9091
[16:50:29] Finished 'serve-nospawn-backend' after 116 ms
[BS] [BrowserSync SPA] Running...
[Browsersync] Access URLs:
 ----------------------------------------
       Local: http://localhost:9090/
    External: http://169.254.33.229:9090/
 ----------------------------------------
          UI: http://localhost:3001
 UI External: http://169.254.33.229:3001
 ----------------------------------------
[Browsersync] Serving files from: F:\WORK\work_go\src\github.com\kubernetes\dashboard\.tmp\serve
[Browsersync] Serving files from: F:\WORK\work_go\src\github.com\kubernetes\dashboard\src\app


/**启动应用Serves the application in development mode. Watches 
for changes in the source files to rebuild development artifacts.*/
gulp.task('serve-nospawn-backend', ['watch-nobackend'], serveDevelopmentMode);  

//启动browserSync:Serves the application in development mode.
function serveDevelopmentMode() {
  browserSyncInit(
      [
        conf.paths.serve,
        conf.paths.app,  // For assets to work.
      ],
      true);
}

/**Initializes BrowserSync tool. Files are served from baseDir directory list and all API calls
 * are proxied to a running backend instance. When includeBowerComponents is true, requests for
 * paths starting with '/bower_components' are routed to bower components directory.
 * */
function browserSyncInit(baseDir, includeBowerComponents) {
  // Enable custom support for Angular apps, e.g., history management.
  browserSyncInstance.use(browserSyncSpa({
    selector: '[ng-app]',
  }));

  let apiRoute = '/api';
  let proxyMiddlewareOptions = {
    target: `http://localhost:${conf.backend.devServerPort}`,
    // proxy websockets
    ws: true,
  };

  let config = {
    browser: [],       // Needed so that the browser does not auto-launch.
    directory: false,  // Disable directory listings.
    // TODO(bryk): Add proxy to the backend here.
    server: {
      baseDir: baseDir,
      middleware: proxyMiddleware(apiRoute, proxyMiddlewareOptions),
    },
    port: conf.frontend.serverPort,
    startPath: '/',
    notify: false,
  };

  if (includeBowerComponents) {
    config.server.routes = {
      '/bower_components': conf.paths.bowerComponents,
    };
  }

  browserSyncInstance.init(config);
}

//监控前端代码:Watches for changes in source files and runs Gulp tasks to rebuild them.
gulp.task('watch-nobackend', ['index', 'angular-templates'], function() {
    gulp.watch([path.join(conf.paths.frontendSrc, 'index.html'), 'bower.json'], ['index']);

    gulp.watch(
        [
            path.join(conf.paths.frontendSrc, '**/*.scss'),
        ],
        function(event) {
            if (event.type === 'changed') {
                // If this is a file change, rebuild only styles - nothing more is needed.
                gulp.start('styles');
            } else {
                // If this is new/deleted file, everything has to be rebuilt.
                gulp.start('index');
            }
        });

    gulp.watch(path.join(conf.paths.frontendSrc, '**/*.js'), ['scripts-watch']);
    gulp.watch(path.join(conf.paths.frontendSrc, '**/*.html'), ['angular-templates']);
});

//建立index:Creates frontend application index file with development dependencies injected.
gulp.task('index', ['scripts', 'styles'], function() {
  return createIndexFile(conf.paths.serve, true).pipe(webpackStream(webpackOptions));
});

/**注入CSS, js
 * Creates index file in the given directory with dependencies injected from that directory.*/
function createIndexFile(indexPath, dev) {
  let injectStyles = gulp.src(path.join(indexPath, '**/*.css'), {read: false});

  let injectScripts = gulp.src(path.join(indexPath, '**/*.js'), {read: false});

  let injectOptions = {
    // Make the dependencies relative to the deps directory.
    ignorePath: [path.relative(conf.paths.base, indexPath)],
    addRootSlash: false,
    quiet: true,
  };

  /***bower解决了前端库及其依赖安装的问题。至于怎么把真正所须要的文件引入到html文件中,就须要wiredep来帮忙啦
   * <!-- bower:css -->
   <!-- endbower -->
   在.html文件会把默认bower.json的配置自动注入到下面标签中去 <!-- bower:js --> <!-- endbower --> <!-- bower:css--> <!-- endbower -->
   */
  let wiredepOptions = {
    // Make wiredep dependencies begin with "bower_components/" not "../../...".
    ignorePath: path.relative(conf.paths.frontendSrc, conf.paths.base),
  };

  if (dev) {
    wiredepOptions.devDependencies = true;
  }

  return gulp.src(path.join(conf.paths.frontendSrc, 'index.html'))
      .pipe(gulpInject(injectStyles, injectOptions))
      .pipe(gulpInject(injectScripts, injectOptions))
      .pipe(wiredep.stream(wiredepOptions))
      .pipe(gulp.dest(indexPath));
}


/**使用webpack打包js
 * Returns function creating a stream that compiles frontend JavaScript files into development
 * bundle located in {conf.paths.serve} directory. This has to be done because currently browsers do **/
gulp.task('scripts', createScriptsStream(true));
function createScriptsStream(throwError) {
  return function() {
    let webpackOptions = {
      devtool: 'inline-source-map',
      module: {
        // ES6 modules have to be preprocessed with Babel loader to work in browsers.
        loaders: [{test: /\.js$/, exclude: /node_modules/, loaders: ['babel-loader']}],
      },
      output: {filename: 'app-dev.js'},
      resolve: {
        // Set the module resolve root, so that webpack knows how to process non-relative imports.
        // Should be kept in sync with respective Closure Compiler option.
        root: conf.paths.frontendSrc,
      },
      quiet: true,
    };
    let compiled = gulp.src(path.join(conf.paths.frontendSrc, 'index_module.js'))
                       .pipe(webpackStream(webpackOptions));
    if (!throwError) {
      // prevent gulp from crashing during watch task in case of JS syntax errors
      compiled = compiled.on('error', function handleScriptSyntaxError(err) {
        compiled.emit('end');
        console.log(err.toString());
      });
    }

    return compiled.pipe(gulp.dest(conf.paths.serve));
  };
}

/**编译SASS成css
 * Compiles stylesheets and places them into the serve folder. Each stylesheet file is compiled
 * separately.
 */
gulp.task('styles', function() {
  let sassOptions = {
    style: 'expanded',
  };

  return gulp.src(path.join(conf.paths.frontendSrc, '**/*.scss'))
      .pipe(gulpSourcemaps.init())  //当压缩的JS出错,能根据这个找到未压缩代码的位置 不会一片混乱代码
      .pipe(gulpSass(sassOptions))  //预编译Sass
      .pipe(gulpAutoprefixer())     //根据设置浏览器版本自动处理浏览器前缀
      .pipe(gulpSourcemaps.write('.'))  //map文件命名
      .pipe(gulp.dest(conf.paths.serve))
      // If BrowserSync is running, inform it that styles have changed.
      .pipe(browserSyncInstance.stream());
});

browerSync启动注入前端代码,并代理后端服务。
css:browserSyncInstance.stream()
script: webpackStream(webpackOptions)
index: webpackStream(webpackOptions)
注入: .pipe(gulpInject(injectStyles, injectOptions)) .pipe(gulpInject(injectScripts, injectOptions)) .pipe(wiredep.stream(wiredepOptions))

使用到Angular Material,依赖angular-animate, angular-aria(无障碍), angular 使用flex布局,封装flex成本身的样式layout-*,再把layout-*样式和属性关联,使用时直接使用属性。 支持-sm, -md, -gt等自适应的后缀(600,960,1200)