OpenStack实践系列②认证服务Keystone

OpenStack实践系列②认证服务Keystone

三、实战OpenStack之控制节点
3.1 CentOS7的时间同步服务器chrony

下载chrony

# yum install -y chrony

 

修改其配置文件

# vim /etc/chrony.conf
allow 192.168/16

chrony开机自启动,并且启动

# systemctl enable chronyd.service
# systemctl start chronyd.service

 

设置Centos7的时区为Asia/Shanghai

# timedatectl set-timezone Asia/Shanghai

查看时区和时间

# timedatectl status
Local time: Tue 2017-04-25 15:42:22 CST
Universal time: Tue 2017-04-25 07:42:22 UTC
RTC time: Tue 2017-04-25 15:42:22
Time zone: Asia/Shanghai (CST, +0800)
NTP enabled: yes
NTP synchronized: no
RTC in local TZ: no
DST active: n/a

# date
Tue Apr 25 15:42:58 CST 2017

 

3.2 配置mysql

Openstack的所有组件除了Horizon,都要用到数据库,本文使用的是MariaDB
拷贝配置文件

# cp /usr/share/mariadb/my-medium.cnf /etc/my.cnf
cp: overwrite ‘/etc/my.cnf’? y

 


# vim /etc/my.cnf(在mysqld模块下添加如下内容)

[mysqld]
default-storage-engine = innodb # 默认的存储引擎
innodb_file_per_table # 使用独享的表空间
collation-server = utf8_general_ci # 设置校对标准
init-connect = 'SET NAMES utf8' # 设置连接的字符集
character-set-server = utf8 # 设置创建数据库时默认的字符集

开机自启和启动mysql

# systemctl enable mariadb.service
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
[root@node1 ~]# systemctl start mariadb.service
[root@node1 ~]# systemctl status mariadb.service
● mariadb.service - MariaDB 10.1 database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2017-04-25 15:50:54 CST; 10s ago
Process: 21977 ExecStartPost=/usr/libexec/mysql-check-upgrade (code=exited, status=0/SUCCESS)
Process: 21790 ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n (code=exited, status=0/SUCCESS)
Process: 21765 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS)
Main PID: 21947 (mysqld)
Status: "Taking your SQL requests now..."
CGroup: /system.slice/mariadb.service
└─21947 /usr/libexec/mysqld --basedir=/usr

Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: '/usr/bin/mysql_secure_installation'
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: which will also give you the option of removing the test
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: databases and anonymous user created by default. This is
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: strongly recommended for production servers.
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: See the MariaDB Knowledgebase at http://mariadb.com/kb or the
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: MySQL manual for more instructions.
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: Please report any problems at http://mariadb.org/jira
Apr 25 15:50:54 node1.chinasoft.com mysql-prepare-db-dir[21790]: The latest information about MariaDB is available at http://mariadb.org/.
Apr 25 15:50:54 node1.chinasoft.com mysqld[21947]: 2017-04-25 15:50:54 140071239162048 [Note] /usr/libexec/mysqld (mysqld 10.1.20-MariaDB) starting as process 21947 ...
Apr 25 15:50:54 node1.chinasoft.com systemd[1]: Started MariaDB 10.1 database server.
Hint: Some lines were ellipsized, use -l to show in full.

 

设置mysql密码,关闭匿名用户,删除测试数据库

[root@node1 ~]# mysql_secure_installation

创建所有组件的库并授权(生产环境建议配置复杂密码)

# mysql -uroot -proot
执行sql

CREATE DATABASE keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';
CREATE DATABASE glance;
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY 'glance';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY 'glance';
CREATE DATABASE nova;
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' IDENTIFIED BY 'nova';
CREATE DATABASE neutron;
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' IDENTIFIED BY 'neutron';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' IDENTIFIED BY 'neutron';
CREATE DATABASE cinder;
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' IDENTIFIED BY 'cinder';
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' IDENTIFIED BY 'cinder';

 

MariaDB [mysql]> show databases;
+--------------------+
| Database |
+--------------------+
| cinder |
| glance |
| information_schema |
| keystone |
| mysql |
| neutron |
| nova |
| performance_schema |
+--------------------+
8 rows in set (0.00 sec)

 

3.3 Rabbit消息队列

  SOA架构:面向服务的体系结构是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以使用一种统一和通用的方式进行交互。
在这里Openstack采用了SOA架构方案,结合了SOA架构的松耦合特点,单独组件单独部署,每个组件之间可能互为消费者和提供者,通过消息队列(openstack 支持Rabbitmq,Zeromq,Qpid)进行通信,保证了当某个服务当掉的情况,不至于其他都当掉。

启动Rabbitmq

[root@node1 ~]# systemctl enable rabbitmq-server.service
Created symlink from /etc/systemd/system/multi-user.target.wants/rabbitmq-server.service to /usr/lib/systemd/system/rabbitmq-server.service.
[root@node1 ~]# systemctl start rabbitmq-server.service

 

新建Rabbitmq用户并授权

[root@node1 ~]# rabbitmqctl add_user openstack openstack
Creating user "openstack" ...
[root@node1 ~]# rabbitmqctl set_permissions openstack ".*" ".*" ".*"
Setting permissions for user "openstack" in vhost "/" ...

 

启用Rabbitmq的web管理插件

[root@node1 ~]# rabbitmq-plugins enable rabbitmq_management

 

重启Rabbitmq

[root@node1 ~]# systemctl restart rabbitmq-server.service

 

查看Rabbit的端口,其中5672是服务端口,15672是web管理端口,25672是做集群的端口

[root@node1 ~]# netstat -lntup|grep 5672
tcp 0 0 0.0.0.0:15672 0.0.0.0:* LISTEN 23058/beam.smp 
tcp 0 0 0.0.0.0:25672 0.0.0.0:* LISTEN 23058/beam.smp 
tcp6 0 0 :::5672 :::* LISTEN 23058/beam.smp

 

在web界面添加openstack用户,设置权限,首次登陆必须使用账号和密码必须都是guest
http://192.168.3.199:15672/

role设置为administrator,并设置openstack的密码

 

3.4 Keystone组件

修改keystone的配置文件用作无用户时,创建用户来链接,此内容使用openssl随机产生

# openssl rand -hex 15
4ab82b3da89d10c47243bd54487d2d

# vim /etc/keystone/keystone.conf
admin_token = 4ab82b3da89d10c47243bd54487d2d

connection = mysql://keystone:keystone@192.168.3.199/keystone # [database] 部分 用作链接数据库,三个keysthone分别为keystone组件,keystone用户名,mysql中的keysthone库名

 

切换到keystone用户,导入keystoe数据库

# su -s /bin/sh -c "keystone-manage db_sync" keystone

 

检查数据库导入结果

MariaDB [keystone]> show tables;
+------------------------+
| Tables_in_keystone |
+------------------------+
| access_token |
| assignment |
| config_register |
| consumer |
| credential |
| domain |
| endpoint |
| endpoint_group |
| federation_protocol |
| group |
| id_mapping |
| identity_provider |
| idp_remote_ids |
| mapping |
| migrate_version |
| policy |
| policy_association |
| project |
| project_endpoint |
| project_endpoint_group |
| region |
| request_token |
| revocation_event |
| role |
| sensitive_config |
| service |
| service_provider |
| token |
| trust |
| trust_role |
| user |
| user_group_membership |
| whitelisted_config |
+------------------------+
33 rows in set (0.00 sec)

 

# cd /var/log/keystone/
# ll
total 8
-rw-r--r-- 1 keystone keystone 7064 Apr 25 16:17 keystone.log(通过切换到keystone用户下导入数据库,当启动的时候回把日志写入到该日志中,如果使用root执行倒库操作,则无法通过keysthone启动keystone程序)

继续修改/etc/keystone/keystone.conf配置

# vim /etc/keystone/keystone.conf

verbose = true # 开启debug模式
servers = 127.0.0.1:11211 # [memcache]部分 更改servers标签,填写memcache地址
driver = sql # [revoke] 部分 开启默认sql驱动
provider = uuid # [token] 部分 开启并使用唯一识别码
driver = memcache # [token] 部分 (使用用户密码生成token时,存储到memcache中,高性能提供服务)

 

查看更改结果

# grep -n "^[a-Z]" /etc/keystone/keystone.conf
12:admin_token = 4ab82b3da89d10c47243bd54487d2d
107:verbose = true
495:connection = mysql://keystone:keystone@192.168.3.199/keystone
1313:servers = 127.0.0.1:11211
1718:driver = sql
1911:provider = uuid
1916:driver = memcache

 

注意:
memcache配置
很多教程配置都是直接绑定在eth0上,默认安装memcache以后只监听在127.0.0.1上,一定要注意,否则后面keystone认证的时候会报错(大坑)
servers = 192.168.3.199:11211
配置可以用telnet 192.168.3.199 11211验证被拒绝

修改Memcached配置

# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1" # 改为0.0.0.0这样就监听在了所有网卡上

 

添加一个apache的wsgi-keystone配置文件,其中5000端口是提供该服务的,35357是为admin提供管理用的
[root@node1 keystone]# vim /etc/httpd/conf.d/wsgi-keystone.conf

Listen 5000
Listen 35357
<VirtualHost *:5000>
    WSGIDaemonProcess keystone-public processes=5 threads=1 user=keystone group=keystone display-name=%{GROUP}
    WSGIProcessGroup keystone-public
    WSGIScriptAlias / /usr/bin/keystone-wsgi-public
    WSGIApplicationGroup %{GLOBAL}
    WSGIPassAuthorization On
    <IfVersion >= 2.4>
      ErrorLogFormat "%{cu}t %M"
    </IfVersion>
    ErrorLog /var/log/httpd/keystone-error.log
    CustomLog /var/log/httpd/keystone-access.log combined
    <Directory /usr/bin>
        <IfVersion >= 2.4>
            Require all granted
        </IfVersion>
        <IfVersion < 2.4>
            Order allow,deny
            Allow from all
        </IfVersion>
    </Directory>
</VirtualHost>
<VirtualHost *:35357>
    WSGIDaemonProcess keystone-admin processes=5 threads=1 user=keystone group=keystone display-name=%{GROUP}
    WSGIProcessGroup keystone-admin
    WSGIScriptAlias / /usr/bin/keystone-wsgi-admin
    WSGIApplicationGroup %{GLOBAL}
    WSGIPassAuthorization On
    <IfVersion >= 2.4>
      ErrorLogFormat "%{cu}t %M"
    </IfVersion>
    ErrorLog /var/log/httpd/keystone-error.log
    CustomLog /var/log/httpd/keystone-access.log combined
    <Directory /usr/bin>
        <IfVersion >= 2.4>
            Require all granted
        </IfVersion>
        <IfVersion < 2.4>
            Order allow,deny
            Allow from all
        </IfVersion>
    </Directory>
</VirtualHost>

 

配置apache的servername,如果不配置servername,会影响keystone服务

[root@node1 keystone]# vim /etc/httpd/conf/httpd.conf
ServerName 192.168.3.199:80

 

启动memcached,httpd,keystone

[root@node1 keystone]# systemctl enable memcached httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/memcached.service to /usr/lib/systemd/system/memcached.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@node1 keystone]# systemctl start memcached httpd

 

修改默认的memcached监听地址127.0.0.1为0.0.0.0

[root@node1 ~]# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1"

 

查看httpd占用端口情况

[root@node1 keystone]# netstat -lntup|grep httpd
tcp6 0 0 :::80 :::* LISTEN 24007/httpd 
tcp6 0 0 :::35357 :::* LISTEN 24007/httpd 
tcp6 0 0 :::5000 :::* LISTEN 24007/httpd

 

创建用户并连接keystone,在这里可以使用两种方式,通过keystone –help后家参数的方式,或者使用环境变量env的方式,下面就将使用环境变量的方式,分别设置了token,API及控制版本(SOA中很适用)

[root@node1 keystone]# export OS_TOKEN=4ab82b3da89d10c47243bd54487d2d
[root@node1 keystone]# export OS_URL=http://192.168.3.199:35357/v3
[root@node1 keystone]# export OS_IDENTITY_API_VERSION=3

 

创建admin项目(project)

[root@node1 keystone]# openstack project create --domain default --description "Admin Project" admin
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | Admin Project |
| domain_id | default |
| enabled | True |
| id | ddbd3b664df640fb842f791c1c852f8a |
| is_domain | False |
| name | admin |
| parent_id | None |
+-------------+----------------------------------+

 


创建admin用户(user)并设置密码(生产环境建议设置复杂密码)

[root@node1 keystone]# openstack user create --domain default --password-prompt admin
User Password:
Repeat User Password:
+-----------+----------------------------------+
| Field | Value |
+-----------+----------------------------------+
| domain_id | default |
| enabled | True |
| id | 0d0e11a89eec4b9f9812491f967bfc29 |
| name | admin |
+-----------+----------------------------------+

 

创建admin的角色(role)

[root@node1 keystone]# openstack role create admin
+-------+----------------------------------+
| Field | Value |
+-------+----------------------------------+
| id | e07056a7929640eea958d01519d16de4 |
| name | admin |
+-------+----------------------------------+

 

把admin用户加到admin项目,赋予admin角色,把角色,项目,用户关联起来

[root@node1 keystone]# openstack role add --project admin --user admin admin

 

创建一个普通用户demo,demo项目,角色为普通用户(uesr),并把它们关联起来

[root@node1 keystone]# openstack project create --domain default --description "Demo Project" demo
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | Demo Project |
| domain_id | default |
| enabled | True |
| id | 019eaae6f6c049658da8d7c6776201d7 |
| is_domain | False |
| name | demo |
| parent_id | None |
+-------------+----------------------------------+

配置密码也为demo

[root@node1 keystone]# openstack user create --domain default --password=demo demo
+-----------+----------------------------------+
| Field | Value |
+-----------+----------------------------------+
| domain_id | default |
| enabled | True |
| id | 09e4d0b4d57c45e29cea321d1f620de3 |
| name | demo |
+-----------+----------------------------------+

[root@node1 keystone]# openstack role create user
+-------+----------------------------------+
| Field | Value |
+-------+----------------------------------+
| id | 12d9c22c247149e79af8c28e2ef1066c |
| name | user |
+-------+----------------------------------+

[root@node1 keystone]# openstack role add --project demo --user demo user

 

创建一个service的项目,此服务用来管理nova,neuturn,glance等组件的服务

[root@node1 keystone]# openstack project create --domain default --description "Service Project" service
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | Service Project |
| domain_id | default |
| enabled | True |
| id | 7721ff49147445ad8bbc87a3e37534ec |
| is_domain | False |
| name | service |
| parent_id | None |
+-------------+----------------------------------+
查看创建的用户,角色,项目

[root@node1 keystone]# openstack user list
+----------------------------------+-------+
| ID | Name |
+----------------------------------+-------+
| 09e4d0b4d57c45e29cea321d1f620de3 | demo |
| 0d0e11a89eec4b9f9812491f967bfc29 | admin |
+----------------------------------+-------+
[root@node1 keystone]# openstack project list
+----------------------------------+---------+
| ID | Name |
+----------------------------------+---------+
| 019eaae6f6c049658da8d7c6776201d7 | demo |
| 7721ff49147445ad8bbc87a3e37534ec | service |
| ddbd3b664df640fb842f791c1c852f8a | admin |
+----------------------------------+---------+
[root@node1 keystone]# openstack role list
+----------------------------------+-------+
| ID | Name |
+----------------------------------+-------+
| 12d9c22c247149e79af8c28e2ef1066c | user |
| e07056a7929640eea958d01519d16de4 | admin |
+----------------------------------+-------+

 

注册keystone服务,虽然keystone本身是搞注册的,但是自己也需要注册服务
创建keystone认证

[root@node1 keystone]# openstack service create --name keystone --description "OpenStack Identity" identity
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | OpenStack Identity |
| enabled | True |
| id | 826594136e754665bc7c2ffd61e5c60d |
| name | keystone |
| type | identity |
+-------------+----------------------------------+

 

分别创建三种类型的endpoint,分别为public:对外可见,internal内部使用,admin管理使用

[root@node1 keystone]# openstack endpoint create --region RegionOne identity public http://192.168.3.199:5000/v2.0
+--------------+----------------------------------+
| Field | Value |
+--------------+----------------------------------+
| enabled | True |
| id | 1cd6d3b8cb55480eb830722cb8032b04 |
| interface | public |
| region | RegionOne |
| region_id | RegionOne |
| service_id | 826594136e754665bc7c2ffd61e5c60d |
| service_name | keystone |
| service_type | identity |
| url | http://192.168.3.199:5000/v2.0 |
+--------------+----------------------------------+

[root@node1 keystone]# openstack endpoint create --region RegionOne identity internal http://192.168.3.199:5000/v2.0
+--------------+----------------------------------+
| Field | Value |
+--------------+----------------------------------+
| enabled | True |
| id | fe67f7ff5f5344f0aa24079fcd7e9999 |
| interface | internal |
| region | RegionOne |
| region_id | RegionOne |
| service_id | 826594136e754665bc7c2ffd61e5c60d |
| service_name | keystone |
| service_type | identity |
| url | http://192.168.3.199:5000/v2.0 |
+--------------+----------------------------------+

[root@node1 keystone]# openstack endpoint create --region RegionOne identity admin http://192.168.3.199:35357/v2.0
+--------------+----------------------------------+
| Field | Value |
+--------------+----------------------------------+
| enabled | True |
| id | 803bfebdac67435180a0fa0a6df6acba |
| interface | admin |
| region | RegionOne |
| region_id | RegionOne |
| service_id | 826594136e754665bc7c2ffd61e5c60d |
| service_name | keystone |
| service_type | identity |
| url | http://192.168.3.199:35357/v2.0 |
+--------------+----------------------------------+

 

查看创建的endpoint

[root@node1 keystone]# openstack endpoint list
+----------------------------------+-----------+--------------+--------------+---------+-----------+---------------------------------+
| ID | Region | Service Name | Service Type | Enabled | Interface | URL |
+----------------------------------+-----------+--------------+--------------+---------+-----------+---------------------------------+
| 1cd6d3b8cb55480eb830722cb8032b04 | RegionOne | keystone | identity | True | public | http://192.168.3.199:5000/v2.0 |
| 803bfebdac67435180a0fa0a6df6acba | RegionOne | keystone | identity | True | admin | http://192.168.3.199:35357/v2.0 |
| fe67f7ff5f5344f0aa24079fcd7e9999 | RegionOne | keystone | identity | True | internal | http://192.168.3.199:5000/v2.0 |
+----------------------------------+-----------+--------------+--------------+---------+-----------+---------------------------------+

 

链接到keystone,请求token,在这里由于已经添加了用户名和密码,就不再使用token,所有就一定要取消环境变量了

[root@node1 ~]# unset OS_TOKEN
[root@node1 ~]# unset OS_URL
[root@node1 ~]# openstack --os-auth-url http://192.168.3.199:35357/v3 --os-project-domain-id default --os-user-domain-id default --os-project-name admin --os-username admin --os-auth-type password token issue
Password: 
+------------+----------------------------------+
| Field | Value |
+------------+----------------------------------+
| expires | 2017-04-25T12:12:44.648250Z |
| id | b63b05cb3a6d4c438a072d501ad64355 |
| project_id | 7340dd86a8b14e73ac36b6d6385c689c |
| user_id | 4e857cca196e44d6994a3bee058a0274 |
+------------+----------------------------------+

 


报错记录:
[root@node1 keystone]# openstack --os-auth-url http://192.168.3.199:35357/v3 --os-project-domain-id default --os-user-domain-id default --os-project-name admin --os-username admin --os-auth-type password token issue
An unexpected error prevented the server from fulfilling your request. (HTTP 500) (Request-ID: req-1d330a83-ab77-4e0f-8e42-1c8d461aea3b)

通过看日志也没看出啥(/var/log/httpd/keystone-access.log keystone-error.log),其实是memcached监听的IP需要由192.168.3.199改为127.0.0.1
下面的报错可以忽略
2017-04-25 19:05:40.954308 No handlers could be found for logger "oslo_config.cfg"

创建OpenStack的客户端环境的脚本

配置admin和demo用户的环境变量,并添加执行权限,以后执行命令,直接source一下就行了

[root@linux-node1 ~]# cat admin-openrc.sh 
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_PROJECT_NAME=admin
export OS_TENANT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=admin
export OS_AUTH_URL=http://192.168.3.199:35357/v3
export OS_IDENTITY_API_VERSION=3

[root@linux-node1 ~]# cat demo-openrc.sh 
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_PROJECT_NAME=demo
export OS_TENANT_NAME=demo
export OS_USERNAME=demo
export OS_PASSWORD=demo
export OS_AUTH_URL=http://192.168.3.199:5000/v3
export OS_IDENTITY_API_VERSION=3

[root@node1 ~]# chmod +x demo-openrc.sh 
[root@node1 ~]# chmod +x admin-openrc.sh 
[root@node1 ~]# source admin-openrc.sh

 

[root@node1 ~]# openstack token issue
+------------+----------------------------------+
| Field | Value |
+------------+----------------------------------+
| expires | 2017-04-25T12:20:48.242121Z |
| id | c0d9510f39034b779479af4a91f8f3b2 |
| project_id | 7340dd86a8b14e73ac36b6d6385c689c |
| user_id | 4e857cca196e44d6994a3bee058a0274 |
+------------+----------------------------------+

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值